summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolaus Rath <Nikolaus@rath.org>2016-03-09 10:09:26 -0800
committerNikolaus Rath <Nikolaus@rath.org>2016-03-09 10:09:26 -0800
commitac9526150a54ca66ed041376e3081d719f77ce49 (patch)
tree4fb2f289ad39a1fa2404a68e358aa465b829a671
parentc61b583f62b130c1ed987d71d2d149f30702acc5 (diff)
Import s3ql_2.9+dfsg.orig.tar.gz
-rw-r--r--Changes.txt152
-rw-r--r--INSTALL.txt17
-rw-r--r--PKG-INFO2
-rw-r--r--README.rst4
-rwxr-xr-xbin/fsck.s3ql6
-rwxr-xr-xbin/mkfs.s3ql4
-rwxr-xr-xbin/mount.s3ql4
-rwxr-xr-xbin/s3ql_oauth_client26
-rwxr-xr-xbin/s3qladm2
-rwxr-xr-xbin/s3qlcp4
-rwxr-xr-xbin/s3qlctrl6
-rwxr-xr-xbin/s3qllock4
-rwxr-xr-xbin/s3qlrm4
-rwxr-xr-xbin/s3qlstat4
-rwxr-xr-xbin/umount.s3ql4
-rwxr-xr-xcontrib/benchmark.py37
-rwxr-xr-xcontrib/clone_fs.py23
-rw-r--r--contrib/expire_backups.119
-rwxr-xr-xcontrib/expire_backups.py2
-rwxr-xr-xcontrib/fsck_db.py1
-rw-r--r--contrib/pcp.119
-rw-r--r--contrib/s3ql_upstart.conf2
-rwxr-xr-xcontrib/scramble_db.py13
-rw-r--r--doc/latex/manual.aux353
-rw-r--r--doc/latex/manual.log1261
-rw-r--r--doc/latex/manual.out21
-rw-r--r--doc/latex/manual.tex573
-rw-r--r--doc/latex/manual.toc144
-rw-r--r--doc/man/fsck.s3ql.152
-rw-r--r--doc/man/mkfs.s3ql.119
-rw-r--r--doc/man/mount.s3ql.152
-rw-r--r--doc/man/s3ql_oauth_client.1105
-rw-r--r--doc/man/s3qladm.122
-rw-r--r--doc/man/s3qlcp.119
-rw-r--r--doc/man/s3qlctrl.119
-rw-r--r--doc/man/s3qllock.119
-rw-r--r--doc/man/s3qlrm.119
-rw-r--r--doc/man/s3qlstat.119
-rw-r--r--doc/man/umount.s3ql.119
-rw-r--r--doc/manual.pdfbin244822 -> 251178 bytes
-rw-r--r--rst/authinfo.rst11
-rw-r--r--rst/backends.rst42
-rw-r--r--rst/conf.py8
-rw-r--r--rst/contrib.rst1
-rw-r--r--rst/durability.rst2
-rw-r--r--rst/impl_details.rst8
-rw-r--r--rst/include/about.rst4
-rw-r--r--rst/include/exitcodes.rst11
-rw-r--r--rst/include/postman.rst12
-rw-r--r--rst/installation.rst19
-rw-r--r--rst/issues.rst2
-rw-r--r--rst/man/adm.rst20
-rw-r--r--rst/man/cp.rst23
-rw-r--r--rst/man/ctrl.rst27
-rw-r--r--rst/man/expire_backups.rst23
-rw-r--r--rst/man/fsck.rst52
-rw-r--r--rst/man/index.rst1
-rw-r--r--rst/man/lock.rst25
-rw-r--r--rst/man/mkfs.rst19
-rw-r--r--rst/man/mount.rst51
-rw-r--r--rst/man/oauth_client.rst54
-rw-r--r--rst/man/pcp.rst21
-rw-r--r--rst/man/rm.rst25
-rw-r--r--rst/man/stat.rst23
-rw-r--r--rst/man/umount.rst19
-rw-r--r--rst/mkfs.rst1
-rw-r--r--rst/mount.rst1
-rw-r--r--rst/special.rst14
-rw-r--r--rst/tips.rst2
-rw-r--r--rst/umount.rst4
-rwxr-xr-xruntests.py5783
-rw-r--r--setup.cfg2
-rwxr-xr-xsetup.py37
-rw-r--r--src/s3ql.egg-info/PKG-INFO2
-rw-r--r--src/s3ql.egg-info/SOURCES.txt44
-rw-r--r--src/s3ql.egg-info/entry_points.txt13
-rw-r--r--src/s3ql.egg-info/requires.txt6
-rw-r--r--src/s3ql.egg-info/top_level.txt1
-rw-r--r--src/s3ql/__init__.py2
-rw-r--r--src/s3ql/adm.py42
-rw-r--r--src/s3ql/backends/__init__.py189
-rw-r--r--src/s3ql/backends/common.py453
-rw-r--r--src/s3ql/backends/gs.py135
-rw-r--r--src/s3ql/backends/local.py121
-rw-r--r--src/s3ql/backends/rackspace.py3
-rw-r--r--src/s3ql/backends/s3.py26
-rw-r--r--src/s3ql/backends/s3c.py404
-rw-r--r--src/s3ql/backends/swift.py80
-rw-r--r--src/s3ql/backends/swiftks.py24
-rw-r--r--src/s3ql/block_cache.py123
-rw-r--r--src/s3ql/common.py64
-rw-r--r--src/s3ql/cp.py2
-rw-r--r--src/s3ql/ctrl.py2
-rw-r--r--src/s3ql/daemonize.py2
-rw-r--r--src/s3ql/database.py42
-rw-r--r--src/s3ql/deltadump.c1724
-rw-r--r--src/s3ql/deltadump.pyx54
-rw-r--r--src/s3ql/exit_stack.py4
-rw-r--r--src/s3ql/fs.py128
-rw-r--r--src/s3ql/fsck.py129
-rw-r--r--src/s3ql/inherit_docstrings.py13
-rw-r--r--src/s3ql/inode_cache.py26
-rw-r--r--src/s3ql/lock.py2
-rw-r--r--src/s3ql/logging.py21
-rw-r--r--src/s3ql/metadata.py42
-rw-r--r--src/s3ql/mkfs.py12
-rw-r--r--src/s3ql/mount.py96
-rw-r--r--src/s3ql/multi_lock.py8
-rw-r--r--src/s3ql/oauth_client.py104
-rw-r--r--src/s3ql/parse_args.py28
-rw-r--r--src/s3ql/remove.py2
-rw-r--r--src/s3ql/umount.py20
-rw-r--r--tests/common.py71
-rw-r--r--tests/conftest.py8
-rw-r--r--tests/mock_server.py272
-rwxr-xr-xtests/t1_backends.py1529
-rwxr-xr-xtests/t1_dump.py8
-rwxr-xr-xtests/t1_retry.py11
-rwxr-xr-xtests/t2_block_cache.py103
-rwxr-xr-xtests/t3_fs_api.py26
-rwxr-xr-xtests/t3_fsck.py14
-rwxr-xr-xtests/t3_inode_cache.py6
-rwxr-xr-xtests/t4_adm.py10
-rwxr-xr-xtests/t4_fuse.py14
-rwxr-xr-xtests/t5_cp.py5
-rwxr-xr-xtests/t5_failsafe.py20
-rwxr-xr-xtests/t5_full.py19
-rwxr-xr-xtests/t6_upgrade.py22
-rw-r--r--tests/test.log0
-rw-r--r--tests/test_crit.log0
-rw-r--r--util/cmdline_lexer.py1
-rw-r--r--util/sphinx_pipeinclude.py5
132 files changed, 8199 insertions, 7560 deletions
diff --git a/Changes.txt b/Changes.txt
index 8eaf360..18dec4e 100644
--- a/Changes.txt
+++ b/Changes.txt
@@ -1,3 +1,45 @@
+2014-06-28, S3QL 2.9
+
+ * Fix crash when using swift backend and server uses an
+ authentication URL other than /v1.0.
+
+ * Fixed two test failures when running unit tests as root.
+
+ * Fixed problems when receiving an HTTP error without a well-formed
+ XML body from the remote server (this may happen e.g. due to
+ failure in a transparent proxy or load balancer).
+
+ * S3QL now depends on the defusedxml Python module
+ (https://pypi.python.org/pypi/defusedxml/).
+
+ * S3QL is no longer vulnerable to DOS attacks from malicious backend
+ servers. Previously, a malicious server could induce S3QL to
+ consume arbitrary amounts of memory by recursive XML entity
+ expansion.
+
+ * S3QL now supports Google OAuth2 authentication. To use it, specify
+ 'oauth2' as backend login, and a valid OAuth2 refresh token as
+ backend password. To obtain the refresh token, the (new)
+ s3ql_oauth_client command may be used.
+
+ * S3QL now requires version 3.1 or newer of the dugong module.
+
+ * In some cases, transmission errors when reading storage objects
+ from a backend may have been misreported as corrupted backend
+ objects. This has been fixed.
+
+ * S3QL no longer crashes when data corruption occurs in the first
+ few bytes of an LZMA compressed storage object.
+
+ * S3QL now honors the "Retry-After" HTTP header when receiving an
+ XML error from a storage server.
+
+ * Fixed a crash that could occur when the remote server (or some
+ intermediate proxy) sends a non-XML error response.
+
+ * mount.s3ql and fsck.s3ql now use different exit codes to indicate
+ different failure conditions.
+
2014-03-29, S3QL 2.8.1
* No changes in S3QL itself.
@@ -33,7 +75,7 @@
* S3QL no longer generates warning messages for the first two times
that it has to resend a request to the storage backend. If there
- is no success after the second try, messages are emitted as before.
+ is no success after the second try, messages are emitted as before.
* S3QL now stores multiple copies of the master encryption key to
allow recovery if the backend looses the object holding the
@@ -80,7 +122,7 @@
* mount.s3ql now autodetects a sensible defaults for the
--max-cache-entries and --cachesize options.
-
+
2013-10-19, S3QL 2.5
* Removed a race condition that resulted in a crash when a file was
@@ -105,7 +147,7 @@
* Fixed a problem with error messages from mount.s3ql being lost,
resulting in a file system shutdown for apparently no reason.
-
+
2013-08-27, S3QL 2.4
* Attempts to upgrade a file system that is already at the newest
@@ -174,7 +216,7 @@
* The mount.s3ql --compress option now allows specification of the
compression level in addition to the compression algorithm.
-
+
2013-06-14, S3QL 2.1 (beta)
* S3QL now uses SSL connections by default.
@@ -235,7 +277,7 @@
extended attributes. The previous error code of ENOSYS had the
unintended side effect that some FUSE versions gave up trying to
get/set any extended attributes at all.
-
+
2013-02-23, S3QL 1.13
* Fixed issues when trying to access a directory at the root
@@ -270,8 +312,8 @@
* Fixed a bug that caused malformed metadata to be written out when
using recent eglibc versions (the relevant change in eglibc
was introduced between eglibc versions 2.13 and 2.17).
-
-
+
+
2012-09-03, S3QL 1.12
* Be more verbose about how to remedy the situation when attempting
@@ -308,7 +350,7 @@
the remote server, and no longer fails when attempting to upload
data with an expired auth token. Thanks to Ken
<forken.liu@delta.com.tw> for the report and initial patch!
-
+
2012-02-24, S3QL 1.10
* The s3s, s3cs and gss backends have been removed. Use the new
@@ -324,9 +366,9 @@
2012-01-21, S3QL 1.9
- * Fixed a problem with file and directory time stamps
- changing with the time zone of the mount.s3ql process.
-
+ * Fixed a problem with file and directory time stamps
+ changing with the time zone of the mount.s3ql process.
+
* Fixed a crash in contrib/benchmark.py and made output
(hopefully) easier to understand.
@@ -345,11 +387,11 @@
* S3QL now has experimental proxy support and will honor the
http_proxy and https_proxy environment variables.
-
+
2011-12-06, S3QL 1.8.1
* Fixed direct updates from 1.6 to 1.8.
-
+
2011-12-05, S3QL 1.8
* Fixed "ValueError: Can't dump NULL values" crash when file system
@@ -357,7 +399,7 @@
* Deleting files no longer takes O(number of distinct filenames)
time (bug introduced in 1.7).
-
+
* Improved s3qlcp and directory listing performance for very large
directories.
@@ -382,13 +424,13 @@
smaller than the minimum object size may be combined into groups
that are stored as single objects in the storage backend.
- * Depend on python-llfuse 0.37. This fixes a problem with the file system
+ * Depend on python-llfuse 0.37. This fixes a problem with the file system
effectively blocking any other request while an s3qlrm, s3qllock
or s3qlcp instance is running.
-
- * Fixed some crashes happening under heavily concurrent file system
+
+ * Fixed some crashes happening under heavily concurrent file system
usage.
-
+
2011-11-27, S3QL 1.7
* Extended attribute names are now de-duplicated.
@@ -435,12 +477,12 @@
* Fixed support for prefix in storage urls.
* Retry on timeout when transmitting data to remote server.
-
- * Do not free mount point when terminating due to unhandled
- exception in background thread.
-
+
+ * Do not free mount point when terminating due to unhandled
+ exception in background thread.
+
2011-10-06, S3QL 1.4
-
+
* Metadata is now always LZMA compressed, mount.s3ql's --compress
option only affects compression of file contents.
@@ -452,11 +494,11 @@
2011-10-04, S3QL 1.3
* Fixed an s3qlcp crash happening when source or destination inode
- number was a 64 bit value.
-
+ number was a 64 bit value.
+
* "Connection reset by peer" network errors are now handled
correctly.
-
+
* fsck.s3ql can now renumber inodes. This is useful if the file
system was mounted using S3QL 1.2 or 1.1.x without the --nfs
option and can now no longer be accessed on 32bit systems.
@@ -464,7 +506,7 @@
* Use only 32 bits for inodes, even when --nfs is not specified.
This ensures that file systems can be safely used by both 32 and
64 bit systems.
-
+
2011-09-28, S3QL 1.2
* Fixed a database problem that was responsible for file
@@ -474,7 +516,7 @@
* Fixed a race condition that could cause applications to get just
zero bytes when trying to read from a file that has just been
copied with s3qlcp.
-
+
2011-09-20, S3QL 1.1.4
* Fixed a typo that caused errors when trying to remove any blocks
@@ -484,17 +526,17 @@
(but still not 100% accurate).
* Fixed some theoretical deadlocks.
-
+
* contrib/benchmark.py is now working again and also takes into
account the throughput from userspace to S3QL.
-
+
2011-09-18, S3QL 1.1.3
* Fixed a race condition in the local backend that resulted in
errors of the form "[Errno 17] File exists: [bucket path]".
-
+
* Added Google Storage backend.
-
+
* Added backend for general, S3 compatible storage services.
* Fixed a bug that caused S3QL to complain about the backend having
@@ -532,7 +574,7 @@
backwards compatibility, the default file is now called authinfo2.
* Network errors are now handled much more consistently.
-
+
* There is a new --nfs option for mount.s3ql that needs to be used
when the S3QL file system will be exported over NFS.
@@ -552,7 +594,7 @@
* fsck now checks if all indices have been created. This avoids
a huge performance problem when mount.s3ql was interrupted
after downloading metadata, but before creating the indices.
-
+
2011-07-23, S3QL 1.1 (development version)
* Restructured metadata. This should also significantly reduce the
@@ -560,9 +602,9 @@
* Fixed license typo in file header comments, license
is GNU GPL Version 3, not LGPL.
-
+
* Fixed problem with fsck.s3ql generating extraordinary long
- filenames in /lost+found and then crashing.
+ filenames in /lost+found and then crashing.
* When called as root, use umount rather than fusermount for
compatibility with FUSE4BSD.
@@ -607,12 +649,12 @@
* mkfs.s3ql now has a --force option to overwrite an existing file
system.
-
+
2010-12-30, S3QL 0.29
* The FUSE interface has been rewritten using Cython and factored
out into a separate package, http://code.google.com/p/python-llfuse/.
-
+
This should result in easier installation, better performance and
better maintainability.
@@ -621,25 +663,25 @@
* "s3qlctrl upload-meta" now works even if the file system has been
mounted with --metadata-upload-interval=0.
-
+
* File system metadata is now permanently cached locally. This
significantly reduces the time required to mount the file system.
-
+
* The documentation is now also included in PDF format.
2010-12-11, S3QL 0.27
* The authinfo file now supports passwords that include white space.
-
+
* The s3qladm command can now be used to download metadata backups.
-
+
* The --strip-meta option for mount.s3ql has been removed, redundant
data is now always stripped before upload.
* mount.s3ql now has a --upstart option so that it can easily run as
an upstart job. An example job definition is included in
contrib/s3ql.conf.
-
+
* s3qlctrl now has an 'upload-meta' command to trigger a metadata
upload while the file system is mounted.
@@ -651,8 +693,8 @@
then the affected files may contain additional, old data at the
end that is not supposed to be there.
-
-
+
+
2010-10-30, S3QL 0.26
* Fixed a problem with the sftp backend failing because it tries to
@@ -665,7 +707,7 @@
* A critical bug that could cause backups to be deleted too early
and potentially break the whole backup strategy has been fixed in
contrib/expire_backups.py.
-
+
The new version has changed semantics that and also copes
significantly better when backups are made in irregular time
intervals.
@@ -673,7 +715,7 @@
* S3QL should now respond with more consistent performance when
accessing the file system while s3qlcp, s3qllock or s3qlrm is
running at the same time.
-
+
* When enabling debug output for the `UploadManager` module, S3QL
now logs detailed messages about de-duplication, upload and
compression performance.
@@ -682,19 +724,19 @@
* Fixed a deadlock that could cause the mount.s3ql process to hang
around after umount.
-
+
* Fixed a bug that caused S3QL to consider all downloaded blocks as
dirty and resulted in unneccessary checksum calculations on
expiration.
* s3qlctrl can now change the log level at runtime.
-
+
* s3qladm delete now also deletes any local stale cache files.
-
+
* Periodic metadata upload can now be disabled completely by
specifying an interval of zero.
-
-
+
+
2010-09-03, S3QL 0.23
* Fixed problem with global_lock.py not being installed by setup.py
@@ -729,10 +771,10 @@
found in the contrib/ directory.
* S3QL now comes with sample backup script in contrib/s3_backup.sh
-
+
* Added contrib/pcp.py, an rsync wrapper to recursively copy
directory trees with several parallel rsync processes.
-
+
2010-08-01, S3QL 0.20.1
* Hotfix for s3qladm upgrade.
@@ -780,7 +822,7 @@
* The local and sftp backends now spread their files into different
sub-directories.
-
+
* Amazon S3 Reduced Redundancy Storage (RRS) is now supported. To
use it, use a storage url of the form s3rr://<bucket> instead of
s3://<bucket>.
diff --git a/INSTALL.txt b/INSTALL.txt
deleted file mode 100644
index 3a7685c..0000000
--- a/INSTALL.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-Installation
-------------
-
-S3QL depends on several other programs and libraries that have to be installed
-first. The best method to satisfy these dependencies depends on your
-distribution. In some cases S3QL and all its dependencies can be installed with as
-little as three commands, while in other cases more work may be required.
-
-The S3QL Wiki contains installation instructions for quite a few different
-Linux distributions:
-
- http://code.google.com/p/s3ql/w/list?q=label:Installation
-
-If your distribution is not included in this list, you can fall back on the
-more detailed, but also more complex General Installation Instructions in the
-S3QL User's Guide (which is included in the doc/ directory and available
-online on http://www.rath.org/s3ql-docs/).
diff --git a/PKG-INFO b/PKG-INFO
index 17e56dd..4784902 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: s3ql
-Version: 2.8.1
+Version: 2.9
Summary: a full-featured file system for online data storage
Home-page: https://bitbucket.org/nikratio/s3ql/
Author: Nikolaus Rath
diff --git a/README.rst b/README.rst
index 10a4677..c7d72d2 100644
--- a/README.rst
+++ b/README.rst
@@ -38,7 +38,7 @@ Features
sizes up to 2 TB.
* **Dynamic Size.** The size of an S3QL file system grows and shrinks
- dynamically as required.
+ dynamically as required.
* **Compression.** Before storage, all data may compressed with the
LZMA, bzip2 or deflate (gzip) algorithm.
@@ -125,4 +125,4 @@ and the `User's Guide`_ for more information.
.. _`User's Guide`: http://www.rath.org/s3ql-docs/index.html
.. _`S3QL wiki`: https://bitbucket.org/nikratio/s3ql/wiki/
-.. _`Installation Instructions`: https://bitbucket.org/nikratio/s3ql/wiki/Installation%20Instructions
+.. _`Installation Instructions`: https://bitbucket.org/nikratio/s3ql/wiki/Installation
diff --git a/bin/fsck.s3ql b/bin/fsck.s3ql
index 5d88e3f..ec2feca 100755
--- a/bin/fsck.s3ql
+++ b/bin/fsck.s3ql
@@ -16,11 +16,11 @@ basedir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-
-# When running from HG repo, enable all warnings
+
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.fsck
s3ql.fsck.main(sys.argv[1:])
diff --git a/bin/mkfs.s3ql b/bin/mkfs.s3ql
index 7e4b345..084c03b 100755
--- a/bin/mkfs.s3ql
+++ b/bin/mkfs.s3ql
@@ -17,10 +17,10 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.mkfs
s3ql.mkfs.main(sys.argv[1:])
diff --git a/bin/mount.s3ql b/bin/mount.s3ql
index 0777e6f..e2384be 100755
--- a/bin/mount.s3ql
+++ b/bin/mount.s3ql
@@ -17,10 +17,10 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.mount
s3ql.mount.main(sys.argv[1:])
diff --git a/bin/s3ql_oauth_client b/bin/s3ql_oauth_client
new file mode 100755
index 0000000..aa407f6
--- /dev/null
+++ b/bin/s3ql_oauth_client
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+'''
+s3ql_oauth_client - this file is part of S3QL (http://s3ql.googlecode.com)
+
+Copyright (C) Nikolaus Rath <Nikolaus@rath.org>
+
+This program can be distributed under the terms of the GNU GPLv3.
+'''
+
+import sys
+import os.path
+
+# We are running from the S3QL source directory, make sure
+# that we use modules from this directory
+basedir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
+if (os.path.exists(os.path.join(basedir, 'setup.py')) and
+ os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
+ sys.path = [os.path.join(basedir, 'src')] + sys.path
+
+# When running from HG repo, enable all warnings
+if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
+ import warnings
+ warnings.simplefilter('default')
+
+import s3ql.oauth_client
+s3ql.oauth_client.main(sys.argv[1:])
diff --git a/bin/s3qladm b/bin/s3qladm
index 87b9c6a..6f0c190 100755
--- a/bin/s3qladm
+++ b/bin/s3qladm
@@ -17,7 +17,7 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
diff --git a/bin/s3qlcp b/bin/s3qlcp
index bdb4dfd..06de1ed 100755
--- a/bin/s3qlcp
+++ b/bin/s3qlcp
@@ -17,10 +17,10 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.cp
s3ql.cp.main(sys.argv[1:])
diff --git a/bin/s3qlctrl b/bin/s3qlctrl
index 4706d4a..7a2d625 100755
--- a/bin/s3qlctrl
+++ b/bin/s3qlctrl
@@ -16,11 +16,11 @@ basedir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..'))
if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-
-# When running from HG repo, enable all warnings
+
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.ctrl
s3ql.ctrl.main(sys.argv[1:])
diff --git a/bin/s3qllock b/bin/s3qllock
index 9794080..f367f65 100755
--- a/bin/s3qllock
+++ b/bin/s3qllock
@@ -17,10 +17,10 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.lock
s3ql.lock.main(sys.argv[1:])
diff --git a/bin/s3qlrm b/bin/s3qlrm
index b8e03a6..2704523 100755
--- a/bin/s3qlrm
+++ b/bin/s3qlrm
@@ -17,11 +17,11 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.remove
s3ql.remove.main(sys.argv[1:])
diff --git a/bin/s3qlstat b/bin/s3qlstat
index 9d2fade..cf81734 100755
--- a/bin/s3qlstat
+++ b/bin/s3qlstat
@@ -17,10 +17,10 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.statfs
s3ql.statfs.main(sys.argv[1:])
diff --git a/bin/umount.s3ql b/bin/umount.s3ql
index bc868b1..8316524 100755
--- a/bin/umount.s3ql
+++ b/bin/umount.s3ql
@@ -17,10 +17,10 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
os.path.exists(os.path.join(basedir, 'src', 's3ql', '__init__.py'))):
sys.path = [os.path.join(basedir, 'src')] + sys.path
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
import warnings
warnings.simplefilter('default')
-
+
import s3ql.umount
s3ql.umount.main(sys.argv[1:])
diff --git a/contrib/benchmark.py b/contrib/benchmark.py
index 28a011e..90dd671 100755
--- a/contrib/benchmark.py
+++ b/contrib/benchmark.py
@@ -31,7 +31,8 @@ else:
exec_prefix = ''
from s3ql.logging import logging, setup_logging, QuietError
-from s3ql.backends.common import get_backend, BetterBackend, DanglingStorageURLError
+from s3ql.backends import get_backend
+from s3ql.backends.common import BetterBackend, DanglingStorageURLError
from s3ql.backends.local import Backend
from s3ql.common import BUFSIZE
from s3ql.parse_args import ArgumentParser
@@ -57,7 +58,7 @@ def parse_args(args):
help='File to transfer')
parser.add_argument('--threads', metavar='<n>', type=int, default=None,
help='Also include statistics for <n> threads in results.')
-
+
parser.add_cachedir()
return parser.parse_args(args)
@@ -78,7 +79,7 @@ def main(args=None):
buf = src.read(BUFSIZE)
rnd_fh.write(buf)
copied += len(buf)
-
+
log.info('Measuring throughput to cache...')
backend_dir = tempfile.mkdtemp(prefix='s3ql-benchmark-')
mnt_dir = tempfile.mkdtemp(prefix='s3ql-mnt')
@@ -89,16 +90,16 @@ def main(args=None):
for blocksize in block_sizes:
write_time = 0
size = 50 * 1024 * 1024
- while write_time < 3:
- log.debug('Write took %.3g seconds, retrying', write_time)
+ while write_time < 3:
+ log.debug('Write took %.3g seconds, retrying', write_time)
subprocess.check_call([exec_prefix + 'mkfs.s3ql', '--plain', 'local://%s' % backend_dir,
'--quiet', '--force', '--cachedir', options.cachedir])
subprocess.check_call([exec_prefix + 'mount.s3ql', '--threads', '1', '--quiet',
'--cachesize', '%d' % (2 * size / 1024), '--log',
'%s/mount.log' % backend_dir, '--cachedir', options.cachedir,
'local://%s' % backend_dir, mnt_dir])
- try:
- size *= 2
+ try:
+ size *= 2
with open('%s/bigfile' % mnt_dir, 'wb', 0) as dst:
rnd_fh.seek(0)
write_time = time.time()
@@ -115,11 +116,11 @@ def main(args=None):
os.unlink('%s/bigfile' % mnt_dir)
finally:
subprocess.check_call([exec_prefix + 'umount.s3ql', mnt_dir])
-
+
fuse_speed = copied / write_time
log.info('Cache throughput with %3d KiB blocks: %d KiB/sec',
blocksize / 1024, fuse_speed / 1024)
-
+
# Upload random data to prevent effects of compression
# on the network layer
log.info('Measuring raw backend throughput..')
@@ -127,7 +128,7 @@ def main(args=None):
backend = get_backend(options, plain=True)
except DanglingStorageURLError as exc:
raise QuietError(str(exc)) from None
-
+
upload_time = 0
size = 512 * 1024
while upload_time < 10:
@@ -167,7 +168,7 @@ def main(args=None):
if not buf:
break
dst.write(buf)
- return (dst, stamp)
+ return (dst, stamp)
(dst_fh, stamp) = backend.perform_write(do_write, 's3ql_testdata')
dt = time.time() - stamp
in_speed[alg] = size / dt
@@ -178,17 +179,17 @@ def main(args=None):
print('')
print('With %d KiB blocks, maximum performance for different compression'
% (block_sizes[-1]/1024), 'algorithms and thread counts is:', '', sep='\n')
-
+
threads = set([1,2,4,8])
cores = os.sysconf('SC_NPROCESSORS_ONLN')
if cores != -1:
threads.add(cores)
if options.threads:
threads.add(options.threads)
-
+
print('%-26s' % 'Threads:',
('%12d' * len(threads)) % tuple(sorted(threads)))
-
+
for alg in ALGS:
speeds = []
limits = []
@@ -203,16 +204,16 @@ def main(args=None):
if speed / in_speed[alg] * out_speed[alg] > backend_speed:
limit = 'uplink'
speed = backend_speed * in_speed[alg] / out_speed[alg]
-
+
limits.append(limit)
- speeds.append(speed / 1024)
+ speeds.append(speed / 1024)
print('%-26s' % ('Max FS throughput (%s):' % alg),
('%7d KiB/s' * len(threads)) % tuple(speeds))
print('%-26s' % '..limited by:',
('%12s' * len(threads)) % tuple(limits))
-
- print('')
+
+ print('')
print('All numbers assume that the test file is representative and that',
'there are enough processor cores to run all active threads in parallel.',
'To compensate for network latency, you should use about twice as',
diff --git a/contrib/clone_fs.py b/contrib/clone_fs.py
index 18b5589..e5c9bba 100755
--- a/contrib/clone_fs.py
+++ b/contrib/clone_fs.py
@@ -24,7 +24,8 @@ if (os.path.exists(os.path.join(basedir, 'setup.py')) and
sys.path = [os.path.join(basedir, 'src')] + sys.path
from s3ql.logging import logging, setup_logging, QuietError
-from s3ql.backends.common import get_backend, DanglingStorageURLError
+from s3ql.backends import get_backend
+from s3ql.backends.common import DanglingStorageURLError
from s3ql.common import BUFSIZE
from s3ql.parse_args import ArgumentParser, storage_url_type
@@ -41,7 +42,7 @@ def parse_args(args):
parser.add_debug()
parser.add_ssl()
parser.add_version()
-
+
parser.add_argument("src_storage_url", metavar='<source-storage-url>',
type=storage_url_type,
help='Storage URL of the source backend that contains the file system')
@@ -61,13 +62,13 @@ def copy_loop(queue, src_backend, dst_backend):
Terminate when None is received.
'''
-
+
tmpfh = tempfile.TemporaryFile()
while True:
key = queue.get()
if key is None:
break
-
+
log.debug('reading object %s', key)
def do_read(fh):
tmpfh.seek(0)
@@ -79,7 +80,7 @@ def copy_loop(queue, src_backend, dst_backend):
tmpfh.write(buf)
return fh.metadata
metadata = src_backend.perform_read(do_read, key)
-
+
log.debug('writing object %s', key)
def do_write(fh):
tmpfh.seek(0)
@@ -89,7 +90,7 @@ def copy_loop(queue, src_backend, dst_backend):
break
fh.write(buf)
dst_backend.perform_write(do_write, key, metadata)
-
+
def main(args=None):
if args is None:
args = sys.argv[1:]
@@ -117,7 +118,7 @@ def main(args=None):
t = Thread(target=copy_loop, args=(queue, src_backend, dst_backend))
t.start()
threads.append(t)
-
+
for (i, key) in enumerate(src_backends[-1]):
if i % 500 == 0 and sys.stdout.isatty():
sys.stdout.write('\rCopied %d objects so far...' % i)
@@ -126,12 +127,12 @@ def main(args=None):
for t in threads:
queue.put(None)
-
+
for t in threads:
- t.join()
-
+ t.join()
+
if sys.stdout.isatty():
sys.stdout.write('\n')
-
+
if __name__ == '__main__':
main(sys.argv[1:])
diff --git a/contrib/expire_backups.1 b/contrib/expire_backups.1
index 31ba152..643814d 100644
--- a/contrib/expire_backups.1
+++ b/contrib/expire_backups.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "EXPIRE_BACKUPS" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "EXPIRE_BACKUPS" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
expire_backups \- Intelligently expire old backups
.
@@ -152,10 +152,21 @@ Use \fBs3qlrm\fP command to delete backups.
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBexpire_backups\fP returns exit code 0 if the operation succeeded and 1 if some
-error occured.
+\fBexpire_backups\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
\fBexpire_backups\fP is shipped as part of S3QL, \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/contrib/expire_backups.py b/contrib/expire_backups.py
index 4319c05..6ca1b49 100755
--- a/contrib/expire_backups.py
+++ b/contrib/expire_backups.py
@@ -43,7 +43,7 @@ def parse_args(args):
have at least one backup in each age range at all times. It will keep
exactly as many backups as are required for that and delete any
backups that become redundant.
-
+
Age ranges are specified by giving a list of range boundaries in terms
of backup cycles. Every time you create a new backup, the existing
backups age by one cycle.
diff --git a/contrib/fsck_db.py b/contrib/fsck_db.py
index 4f21f1c..8695cad 100755
--- a/contrib/fsck_db.py
+++ b/contrib/fsck_db.py
@@ -62,4 +62,3 @@ def main(args=None):
if __name__ == '__main__':
main(sys.argv[1:])
-
diff --git a/contrib/pcp.1 b/contrib/pcp.1
index 7282387..96f3ef3 100644
--- a/contrib/pcp.1
+++ b/contrib/pcp.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "PCP" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "PCP" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
pcp \- Recursive, parallel copy of directory trees
.
@@ -75,10 +75,21 @@ Number of rsync processes to use (default: 10).
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBpcp\fP returns exit code 0 if the operation succeeded and 1 if some
-error occured.
+\fBpcp\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
\fBpcp\fP is shipped as part of S3QL, \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/contrib/s3ql_upstart.conf b/contrib/s3ql_upstart.conf
index 866bda3..d6b0b17 100644
--- a/contrib/s3ql_upstart.conf
+++ b/contrib/s3ql_upstart.conf
@@ -1,7 +1,7 @@
#
# This file can be placed in /etc/init. It defines an upstart job that
# takes care of mounting and unmounting an S3QL file system.
-#
+#
description "S3QL Backup File System"
author "Nikolaus Rath <Nikolaus@rath.org>"
diff --git a/contrib/scramble_db.py b/contrib/scramble_db.py
index 2d796ac..6c24dc7 100755
--- a/contrib/scramble_db.py
+++ b/contrib/scramble_db.py
@@ -66,10 +66,10 @@ def main(args=None):
# Check for cached metadata
cachepath = get_backend_cachedir(options.storage_url, options.cachedir)
if not os.path.exists(cachepath + '.params'):
- raise QuietError("No local metadata found.")
+ raise QuietError("No local metadata found.")
param = pickle.load(open(cachepath + '.params', 'rb'))
-
+
# Check revision
if param['revision'] < CURRENT_FS_REV:
raise QuietError('File system revision too old.')
@@ -78,14 +78,14 @@ def main(args=None):
if os.path.exists(DBNAME):
raise QuietError('%s exists, aborting.' % DBNAME)
-
+
log.info('Copying database...')
dst = tempfile.NamedTemporaryFile()
with open(cachepath + '.db', 'rb') as src:
shutil.copyfileobj(src, dst)
dst.flush()
db = Connection(dst.name)
-
+
log.info('Scrambling...')
md5 = lambda x: hashlib.md5(x).hexdigest()
for (id_, name) in db.query('SELECT id, name FROM names'):
@@ -99,11 +99,10 @@ def main(args=None):
for (id_, name) in db.query('SELECT rowid, value FROM ext_attributes'):
db.execute('UPDATE ext_attributes SET value=? WHERE rowid=?',
(md5(name), id_))
-
+
log.info('Saving...')
with open(DBNAME, 'wb+') as fh:
dump_metadata(db, fh)
-
+
if __name__ == '__main__':
main(sys.argv[1:])
-
diff --git a/doc/latex/manual.aux b/doc/latex/manual.aux
index 8834ba1..84ff03c 100644
--- a/doc/latex/manual.aux
+++ b/doc/latex/manual.aux
@@ -24,9 +24,9 @@
\@writefile{toc}{\contentsline {chapter}{\numberline {1}About S3QL}{1}{chapter.1}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
+\newlabel{about:about-s3ql}{{1}{1}{About S3QL}{chapter.1}{}}
\newlabel{about::doc}{{1}{1}{About S3QL}{chapter.1}{}}
\newlabel{about:s3ql-user-s-guide}{{1}{1}{About S3QL}{chapter.1}{}}
-\newlabel{about:about-s3ql}{{1}{1}{About S3QL}{chapter.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Features}{1}{section.1.1}}
\newlabel{about:openstack}{{1.1}{1}{Features}{section.1.1}{}}
\newlabel{about:features}{{1.1}{1}{Features}{section.1.1}{}}
@@ -35,8 +35,8 @@
\@writefile{toc}{\contentsline {chapter}{\numberline {2}Installation}{3}{chapter.2}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
-\newlabel{installation::doc}{{2}{3}{Installation}{chapter.2}{}}
\newlabel{installation:installation}{{2}{3}{Installation}{chapter.2}{}}
+\newlabel{installation::doc}{{2}{3}{Installation}{chapter.2}{}}
\@writefile{toc}{\contentsline {section}{\numberline {2.1}Dependencies}{3}{section.2.1}}
\newlabel{installation:dependencies}{{2.1}{3}{Dependencies}{section.2.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {2.2}Installing S3QL}{4}{section.2.2}}
@@ -49,33 +49,34 @@
\@writefile{toc}{\contentsline {chapter}{\numberline {3}Storage Backends}{7}{chapter.3}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
+\newlabel{backends:py-test}{{3}{7}{Storage Backends}{chapter.3}{}}
\newlabel{backends::doc}{{3}{7}{Storage Backends}{chapter.3}{}}
\newlabel{backends:storage-backends}{{3}{7}{Storage Backends}{chapter.3}{}}
\newlabel{backends:id1}{{3}{7}{Storage Backends}{chapter.3}{}}
-\newlabel{backends:py-test}{{3}{7}{Storage Backends}{chapter.3}{}}
\@writefile{toc}{\contentsline {section}{\numberline {3.1}Google Storage}{7}{section.3.1}}
\newlabel{backends:google-storage}{{3.1}{7}{Google Storage}{section.3.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {3.2}Amazon S3}{7}{section.3.2}}
\newlabel{backends:amazon-s3}{{3.2}{7}{Amazon S3}{section.3.2}{}}
+\newlabel{backends:google-storage-manager}{{3.2}{7}{Amazon S3}{section.3.2}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.1}Reduced Redundancy Storage (RRS)}{8}{subsection.3.2.1}}
\newlabel{backends:reduced-redundancy-storage-rrs}{{3.2.1}{8}{Reduced Redundancy Storage (RRS)}{subsection.3.2.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {3.3}OpenStack/Swift}{8}{section.3.3}}
\newlabel{backends:openstack-swift}{{3.3}{8}{OpenStack/Swift}{section.3.3}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {3.4}Rackspace CloudFiles}{8}{section.3.4}}
-\newlabel{backends:rackspace-cloudfiles}{{3.4}{8}{Rackspace CloudFiles}{section.3.4}{}}
-\newlabel{backends:swift}{{3.4}{8}{Rackspace CloudFiles}{section.3.4}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {3.4}Rackspace CloudFiles}{9}{section.3.4}}
+\newlabel{backends:rackspace-cloudfiles}{{3.4}{9}{Rackspace CloudFiles}{section.3.4}{}}
+\newlabel{backends:swift}{{3.4}{9}{Rackspace CloudFiles}{section.3.4}{}}
\@writefile{toc}{\contentsline {section}{\numberline {3.5}S3 compatible}{9}{section.3.5}}
-\newlabel{backends:s3-compatible}{{3.5}{9}{S3 compatible}{section.3.5}{}}
\newlabel{backends:rackspace}{{3.5}{9}{S3 compatible}{section.3.5}{}}
+\newlabel{backends:s3-compatible}{{3.5}{9}{S3 compatible}{section.3.5}{}}
\@writefile{toc}{\contentsline {section}{\numberline {3.6}Local}{9}{section.3.6}}
\newlabel{backends:local}{{3.6}{9}{Local}{section.3.6}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {4}Important Rules to Avoid Losing Data}{11}{chapter.4}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
-\newlabel{durability:sshfs}{{4}{11}{Important Rules to Avoid Losing Data}{chapter.4}{}}
+\newlabel{durability:durability}{{4}{11}{Important Rules to Avoid Losing Data}{chapter.4}{}}
\newlabel{durability::doc}{{4}{11}{Important Rules to Avoid Losing Data}{chapter.4}{}}
+\newlabel{durability:sshfs}{{4}{11}{Important Rules to Avoid Losing Data}{chapter.4}{}}
\newlabel{durability:important-rules-to-avoid-losing-data}{{4}{11}{Important Rules to Avoid Losing Data}{chapter.4}{}}
-\newlabel{durability:durability}{{4}{11}{Important Rules to Avoid Losing Data}{chapter.4}{}}
\@writefile{toc}{\contentsline {section}{\numberline {4.1}Rules in a Nutshell}{11}{section.4.1}}
\newlabel{durability:rules-in-a-nutshell}{{4.1}{11}{Rules in a Nutshell}{section.4.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {4.2}Consistency Window List}{12}{section.4.2}}
@@ -124,27 +125,27 @@
\newlabel{special::doc}{{8}{23}{Advanced S3QL Features}{chapter.8}{}}
\newlabel{special:advanced-s3ql-features}{{8}{23}{Advanced S3QL Features}{chapter.8}{}}
\@writefile{toc}{\contentsline {section}{\numberline {8.1}Snapshotting and Copy-on-Write}{23}{section.8.1}}
-\newlabel{special:s3qlcp}{{8.1}{23}{Snapshotting and Copy-on-Write}{section.8.1}{}}
\newlabel{special:snapshotting-and-copy-on-write}{{8.1}{23}{Snapshotting and Copy-on-Write}{section.8.1}{}}
+\newlabel{special:s3qlcp}{{8.1}{23}{Snapshotting and Copy-on-Write}{section.8.1}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {8.1.1}Snapshotting vs Hardlinking}{23}{subsection.8.1.1}}
\newlabel{special:snapshotting-vs-hardlinking}{{8.1.1}{23}{Snapshotting vs Hardlinking}{subsection.8.1.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {8.2}Getting Statistics}{24}{section.8.2}}
\newlabel{special:getting-statistics}{{8.2}{24}{Getting Statistics}{section.8.2}{}}
\newlabel{special:s3qlstat}{{8.2}{24}{Getting Statistics}{section.8.2}{}}
\@writefile{toc}{\contentsline {section}{\numberline {8.3}Immutable Trees}{24}{section.8.3}}
-\newlabel{special:s3qllock}{{8.3}{24}{Immutable Trees}{section.8.3}{}}
\newlabel{special:immutable-trees}{{8.3}{24}{Immutable Trees}{section.8.3}{}}
+\newlabel{special:s3qllock}{{8.3}{24}{Immutable Trees}{section.8.3}{}}
\@writefile{toc}{\contentsline {section}{\numberline {8.4}Fast Recursive Removal}{24}{section.8.4}}
-\newlabel{special:s3qlrm}{{8.4}{24}{Fast Recursive Removal}{section.8.4}{}}
\newlabel{special:fast-recursive-removal}{{8.4}{24}{Fast Recursive Removal}{section.8.4}{}}
+\newlabel{special:s3qlrm}{{8.4}{24}{Fast Recursive Removal}{section.8.4}{}}
\@writefile{toc}{\contentsline {section}{\numberline {8.5}Runtime Configuration}{25}{section.8.5}}
\newlabel{special:runtime-configuration}{{8.5}{25}{Runtime Configuration}{section.8.5}{}}
\newlabel{special:s3qlctrl}{{8.5}{25}{Runtime Configuration}{section.8.5}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {9}Unmounting}{27}{chapter.9}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
-\newlabel{umount::doc}{{9}{27}{Unmounting}{chapter.9}{}}
\newlabel{umount:unmounting}{{9}{27}{Unmounting}{chapter.9}{}}
+\newlabel{umount::doc}{{9}{27}{Unmounting}{chapter.9}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {10}Checking for Errors}{29}{chapter.10}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
@@ -154,13 +155,13 @@
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{authinfo::doc}{{11}{31}{Storing Authentication Information}{chapter.11}{}}
-\newlabel{authinfo:storing-authentication-information}{{11}{31}{Storing Authentication Information}{chapter.11}{}}
\newlabel{authinfo:authinfo}{{11}{31}{Storing Authentication Information}{chapter.11}{}}
+\newlabel{authinfo:storing-authentication-information}{{11}{31}{Storing Authentication Information}{chapter.11}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {12}Contributed Programs}{33}{chapter.12}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
-\newlabel{contrib::doc}{{12}{33}{Contributed Programs}{chapter.12}{}}
\newlabel{contrib:contributed-programs}{{12}{33}{Contributed Programs}{chapter.12}{}}
+\newlabel{contrib::doc}{{12}{33}{Contributed Programs}{chapter.12}{}}
\@writefile{toc}{\contentsline {section}{\numberline {12.1}benchmark.py}{33}{section.12.1}}
\newlabel{contrib:benchmark-py}{{12.1}{33}{benchmark.py}{section.12.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {12.2}s3\_copy.py}{33}{section.12.2}}
@@ -180,13 +181,13 @@
\newlabel{tips::doc}{{13}{37}{Tips \& Tricks}{chapter.13}{}}
\newlabel{tips:tips-tricks}{{13}{37}{Tips \& Tricks}{chapter.13}{}}
\@writefile{toc}{\contentsline {section}{\numberline {13.1}SSH Backend}{37}{section.13.1}}
-\newlabel{tips:ssh-backend}{{13.1}{37}{SSH Backend}{section.13.1}{}}
\newlabel{tips:ssh-tipp}{{13.1}{37}{SSH Backend}{section.13.1}{}}
+\newlabel{tips:ssh-backend}{{13.1}{37}{SSH Backend}{section.13.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {13.2}Permanently mounted backup file system}{37}{section.13.2}}
\newlabel{tips:permanently-mounted-backup-file-system}{{13.2}{37}{Permanently mounted backup file system}{section.13.2}{}}
\@writefile{toc}{\contentsline {section}{\numberline {13.3}Improving copy performance}{37}{section.13.3}}
-\newlabel{tips:improving-copy-performance}{{13.3}{37}{Improving copy performance}{section.13.3}{}}
\newlabel{tips:copy-performance}{{13.3}{37}{Improving copy performance}{section.13.3}{}}
+\newlabel{tips:improving-copy-performance}{{13.3}{37}{Improving copy performance}{section.13.3}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {14}Known Issues}{39}{chapter.14}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
@@ -199,20 +200,20 @@
\newlabel{man/index:manpages}{{15}{41}{Manpages}{chapter.15}{}}
\@writefile{toc}{\contentsline {section}{\numberline {15.1}The \textbf {mkfs.s3ql} command}{41}{section.15.1}}
\newlabel{man/mkfs::doc}{{15.1}{41}{The \textbf {mkfs.s3ql} command}{section.15.1}{}}
-\newlabel{man/mkfs:the-mkfs-s3ql-command}{{15.1}{41}{The \textbf {mkfs.s3ql} command}{section.15.1}{}}
+\newlabel{man/mkfs:the-command-command}{{15.1}{41}{The \textbf {mkfs.s3ql} command}{section.15.1}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.1.1}Synopsis}{41}{subsection.15.1.1}}
\newlabel{man/mkfs:synopsis}{{15.1.1}{41}{Synopsis}{subsection.15.1.1}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.1.2}Description}{41}{subsection.15.1.2}}
\newlabel{man/mkfs:description}{{15.1.2}{41}{Description}{subsection.15.1.2}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.1.3}Options}{41}{subsection.15.1.3}}
\newlabel{man/mkfs:options}{{15.1.3}{41}{Options}{subsection.15.1.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.1.4}Exit Status}{42}{subsection.15.1.4}}
-\newlabel{man/mkfs:exit-status}{{15.1.4}{42}{Exit Status}{subsection.15.1.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.1.4}Exit Codes}{42}{subsection.15.1.4}}
+\newlabel{man/mkfs:exit-codes}{{15.1.4}{42}{Exit Codes}{subsection.15.1.4}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.1.5}See Also}{42}{subsection.15.1.5}}
\newlabel{man/mkfs:see-also}{{15.1.5}{42}{See Also}{subsection.15.1.5}{}}
\@writefile{toc}{\contentsline {section}{\numberline {15.2}The \textbf {s3qladm} command}{42}{section.15.2}}
\newlabel{man/adm::doc}{{15.2}{42}{The \textbf {s3qladm} command}{section.15.2}{}}
-\newlabel{man/adm:the-s3qladm-command}{{15.2}{42}{The \textbf {s3qladm} command}{section.15.2}{}}
+\newlabel{man/adm:the-command-command}{{15.2}{42}{The \textbf {s3qladm} command}{section.15.2}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.2.1}Synopsis}{42}{subsection.15.2.1}}
\newlabel{man/adm:synopsis}{{15.2.1}{42}{Synopsis}{subsection.15.2.1}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.2.2}Description}{42}{subsection.15.2.2}}
@@ -221,165 +222,179 @@
\newlabel{man/adm:options}{{15.2.3}{42}{Options}{subsection.15.2.3}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.2.4}Actions}{43}{subsection.15.2.4}}
\newlabel{man/adm:actions}{{15.2.4}{43}{Actions}{subsection.15.2.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.2.5}Exit Status}{43}{subsection.15.2.5}}
-\newlabel{man/adm:exit-status}{{15.2.5}{43}{Exit Status}{subsection.15.2.5}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.2.5}Exit Codes}{43}{subsection.15.2.5}}
+\newlabel{man/adm:exit-codes}{{15.2.5}{43}{Exit Codes}{subsection.15.2.5}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.2.6}See Also}{43}{subsection.15.2.6}}
\newlabel{man/adm:see-also}{{15.2.6}{43}{See Also}{subsection.15.2.6}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.3}The \textbf {mount.s3ql} command}{43}{section.15.3}}
-\newlabel{man/mount::doc}{{15.3}{43}{The \textbf {mount.s3ql} command}{section.15.3}{}}
-\newlabel{man/mount:the-mount-s3ql-command}{{15.3}{43}{The \textbf {mount.s3ql} command}{section.15.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.3.1}Synopsis}{43}{subsection.15.3.1}}
-\newlabel{man/mount:synopsis}{{15.3.1}{43}{Synopsis}{subsection.15.3.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.3.2}Description}{43}{subsection.15.3.2}}
-\newlabel{man/mount:description}{{15.3.2}{43}{Description}{subsection.15.3.2}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.3}The \textbf {mount.s3ql} command}{44}{section.15.3}}
+\newlabel{man/mount::doc}{{15.3}{44}{The \textbf {mount.s3ql} command}{section.15.3}{}}
+\newlabel{man/mount:the-command-command}{{15.3}{44}{The \textbf {mount.s3ql} command}{section.15.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.3.1}Synopsis}{44}{subsection.15.3.1}}
+\newlabel{man/mount:synopsis}{{15.3.1}{44}{Synopsis}{subsection.15.3.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.3.2}Description}{44}{subsection.15.3.2}}
+\newlabel{man/mount:description}{{15.3.2}{44}{Description}{subsection.15.3.2}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.3.3}Options}{44}{subsection.15.3.3}}
\newlabel{man/mount:options}{{15.3.3}{44}{Options}{subsection.15.3.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.3.4}Exit Status}{45}{subsection.15.3.4}}
-\newlabel{man/mount:exit-status}{{15.3.4}{45}{Exit Status}{subsection.15.3.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.3.4}Exit Codes}{45}{subsection.15.3.4}}
+\newlabel{man/mount:exit-codes}{{15.3.4}{45}{Exit Codes}{subsection.15.3.4}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.3.5}See Also}{45}{subsection.15.3.5}}
\newlabel{man/mount:see-also}{{15.3.5}{45}{See Also}{subsection.15.3.5}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.4}The \textbf {s3qlstat} command}{45}{section.15.4}}
-\newlabel{man/stat::doc}{{15.4}{45}{The \textbf {s3qlstat} command}{section.15.4}{}}
-\newlabel{man/stat:the-s3qlstat-command}{{15.4}{45}{The \textbf {s3qlstat} command}{section.15.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.1}Synopsis}{45}{subsection.15.4.1}}
-\newlabel{man/stat:synopsis}{{15.4.1}{45}{Synopsis}{subsection.15.4.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.2}Description}{45}{subsection.15.4.2}}
-\newlabel{man/stat:description}{{15.4.2}{45}{Description}{subsection.15.4.2}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.3}Options}{45}{subsection.15.4.3}}
-\newlabel{man/stat:options}{{15.4.3}{45}{Options}{subsection.15.4.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.4}Exit Status}{45}{subsection.15.4.4}}
-\newlabel{man/stat:exit-status}{{15.4.4}{45}{Exit Status}{subsection.15.4.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.5}See Also}{45}{subsection.15.4.5}}
-\newlabel{man/stat:see-also}{{15.4.5}{45}{See Also}{subsection.15.4.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.4}The \textbf {s3qlstat} command}{46}{section.15.4}}
+\newlabel{man/stat::doc}{{15.4}{46}{The \textbf {s3qlstat} command}{section.15.4}{}}
+\newlabel{man/stat:the-command-command}{{15.4}{46}{The \textbf {s3qlstat} command}{section.15.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.1}Synopsis}{46}{subsection.15.4.1}}
+\newlabel{man/stat:synopsis}{{15.4.1}{46}{Synopsis}{subsection.15.4.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.2}Description}{46}{subsection.15.4.2}}
+\newlabel{man/stat:description}{{15.4.2}{46}{Description}{subsection.15.4.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.3}Options}{46}{subsection.15.4.3}}
+\newlabel{man/stat:options}{{15.4.3}{46}{Options}{subsection.15.4.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.4}Exit Codes}{46}{subsection.15.4.4}}
+\newlabel{man/stat:exit-codes}{{15.4.4}{46}{Exit Codes}{subsection.15.4.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.4.5}See Also}{46}{subsection.15.4.5}}
+\newlabel{man/stat:see-also}{{15.4.5}{46}{See Also}{subsection.15.4.5}{}}
\@writefile{toc}{\contentsline {section}{\numberline {15.5}The \textbf {s3qlctrl} command}{46}{section.15.5}}
\newlabel{man/ctrl::doc}{{15.5}{46}{The \textbf {s3qlctrl} command}{section.15.5}{}}
-\newlabel{man/ctrl:the-s3qlctrl-command}{{15.5}{46}{The \textbf {s3qlctrl} command}{section.15.5}{}}
+\newlabel{man/ctrl:the-command-command}{{15.5}{46}{The \textbf {s3qlctrl} command}{section.15.5}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.1}Synopsis}{46}{subsection.15.5.1}}
\newlabel{man/ctrl:synopsis}{{15.5.1}{46}{Synopsis}{subsection.15.5.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.2}Description}{46}{subsection.15.5.2}}
-\newlabel{man/ctrl:description}{{15.5.2}{46}{Description}{subsection.15.5.2}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.3}Options}{46}{subsection.15.5.3}}
-\newlabel{man/ctrl:options}{{15.5.3}{46}{Options}{subsection.15.5.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.4}Exit Status}{46}{subsection.15.5.4}}
-\newlabel{man/ctrl:exit-status}{{15.5.4}{46}{Exit Status}{subsection.15.5.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.5}See Also}{46}{subsection.15.5.5}}
-\newlabel{man/ctrl:see-also}{{15.5.5}{46}{See Also}{subsection.15.5.5}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.6}The \textbf {s3qlcp} command}{47}{section.15.6}}
-\newlabel{man/cp::doc}{{15.6}{47}{The \textbf {s3qlcp} command}{section.15.6}{}}
-\newlabel{man/cp:the-s3qlcp-command}{{15.6}{47}{The \textbf {s3qlcp} command}{section.15.6}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.1}Synopsis}{47}{subsection.15.6.1}}
-\newlabel{man/cp:synopsis}{{15.6.1}{47}{Synopsis}{subsection.15.6.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.2}Description}{47}{subsection.15.6.2}}
-\newlabel{man/cp:description}{{15.6.2}{47}{Description}{subsection.15.6.2}{}}
-\@writefile{toc}{\contentsline {subsubsection}{Snapshotting vs Hardlinking}{47}{subsubsection*.3}}
-\newlabel{man/cp:snapshotting-vs-hardlinking}{{15.6.2}{47}{Snapshotting vs Hardlinking}{subsubsection*.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.3}Options}{47}{subsection.15.6.3}}
-\newlabel{man/cp:options}{{15.6.3}{47}{Options}{subsection.15.6.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.4}Exit Status}{48}{subsection.15.6.4}}
-\newlabel{man/cp:exit-status}{{15.6.4}{48}{Exit Status}{subsection.15.6.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.5}See Also}{48}{subsection.15.6.5}}
-\newlabel{man/cp:see-also}{{15.6.5}{48}{See Also}{subsection.15.6.5}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.7}The \textbf {s3qlrm} command}{48}{section.15.7}}
-\newlabel{man/rm::doc}{{15.7}{48}{The \textbf {s3qlrm} command}{section.15.7}{}}
-\newlabel{man/rm:the-s3qlrm-command}{{15.7}{48}{The \textbf {s3qlrm} command}{section.15.7}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.1}Synopsis}{48}{subsection.15.7.1}}
-\newlabel{man/rm:synopsis}{{15.7.1}{48}{Synopsis}{subsection.15.7.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.2}Description}{48}{subsection.15.7.2}}
-\newlabel{man/rm:description}{{15.7.2}{48}{Description}{subsection.15.7.2}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.3}Options}{48}{subsection.15.7.3}}
-\newlabel{man/rm:options}{{15.7.3}{48}{Options}{subsection.15.7.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.4}Exit Status}{48}{subsection.15.7.4}}
-\newlabel{man/rm:exit-status}{{15.7.4}{48}{Exit Status}{subsection.15.7.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.5}See Also}{48}{subsection.15.7.5}}
-\newlabel{man/rm:see-also}{{15.7.5}{48}{See Also}{subsection.15.7.5}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.8}The \textbf {s3qllock} command}{49}{section.15.8}}
-\newlabel{man/lock::doc}{{15.8}{49}{The \textbf {s3qllock} command}{section.15.8}{}}
-\newlabel{man/lock:the-s3qllock-command}{{15.8}{49}{The \textbf {s3qllock} command}{section.15.8}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.1}Synopsis}{49}{subsection.15.8.1}}
-\newlabel{man/lock:synopsis}{{15.8.1}{49}{Synopsis}{subsection.15.8.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.2}Description}{49}{subsection.15.8.2}}
-\newlabel{man/lock:description}{{15.8.2}{49}{Description}{subsection.15.8.2}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.3}Rationale}{49}{subsection.15.8.3}}
-\newlabel{man/lock:rationale}{{15.8.3}{49}{Rationale}{subsection.15.8.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.4}Options}{49}{subsection.15.8.4}}
-\newlabel{man/lock:options}{{15.8.4}{49}{Options}{subsection.15.8.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.5}Exit Status}{49}{subsection.15.8.5}}
-\newlabel{man/lock:exit-status}{{15.8.5}{49}{Exit Status}{subsection.15.8.5}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.6}See Also}{50}{subsection.15.8.6}}
-\newlabel{man/lock:see-also}{{15.8.6}{50}{See Also}{subsection.15.8.6}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.9}The \textbf {umount.s3ql} command}{50}{section.15.9}}
-\newlabel{man/umount::doc}{{15.9}{50}{The \textbf {umount.s3ql} command}{section.15.9}{}}
-\newlabel{man/umount:the-umount-s3ql-command}{{15.9}{50}{The \textbf {umount.s3ql} command}{section.15.9}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.1}Synopsis}{50}{subsection.15.9.1}}
-\newlabel{man/umount:synopsis}{{15.9.1}{50}{Synopsis}{subsection.15.9.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.2}Description}{50}{subsection.15.9.2}}
-\newlabel{man/umount:description}{{15.9.2}{50}{Description}{subsection.15.9.2}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.3}Options}{50}{subsection.15.9.3}}
-\newlabel{man/umount:options}{{15.9.3}{50}{Options}{subsection.15.9.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.4}Exit Status}{50}{subsection.15.9.4}}
-\newlabel{man/umount:exit-status}{{15.9.4}{50}{Exit Status}{subsection.15.9.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.5}See Also}{50}{subsection.15.9.5}}
-\newlabel{man/umount:see-also}{{15.9.5}{50}{See Also}{subsection.15.9.5}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.10}The \textbf {fsck.s3ql} command}{51}{section.15.10}}
-\newlabel{man/fsck::doc}{{15.10}{51}{The \textbf {fsck.s3ql} command}{section.15.10}{}}
-\newlabel{man/fsck:the-fsck-s3ql-command}{{15.10}{51}{The \textbf {fsck.s3ql} command}{section.15.10}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.1}Synopsis}{51}{subsection.15.10.1}}
-\newlabel{man/fsck:synopsis}{{15.10.1}{51}{Synopsis}{subsection.15.10.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.2}Description}{51}{subsection.15.10.2}}
-\newlabel{man/fsck:description}{{15.10.2}{51}{Description}{subsection.15.10.2}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.3}Options}{51}{subsection.15.10.3}}
-\newlabel{man/fsck:options}{{15.10.3}{51}{Options}{subsection.15.10.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.4}Exit Status}{51}{subsection.15.10.4}}
-\newlabel{man/fsck:exit-status}{{15.10.4}{51}{Exit Status}{subsection.15.10.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.5}See Also}{51}{subsection.15.10.5}}
-\newlabel{man/fsck:see-also}{{15.10.5}{51}{See Also}{subsection.15.10.5}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.11}The \textbf {pcp} command}{52}{section.15.11}}
-\newlabel{man/pcp::doc}{{15.11}{52}{The \textbf {pcp} command}{section.15.11}{}}
-\newlabel{man/pcp:the-pcp-command}{{15.11}{52}{The \textbf {pcp} command}{section.15.11}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.1}Synopsis}{52}{subsection.15.11.1}}
-\newlabel{man/pcp:synopsis}{{15.11.1}{52}{Synopsis}{subsection.15.11.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.2}Description}{52}{subsection.15.11.2}}
-\newlabel{man/pcp:description}{{15.11.2}{52}{Description}{subsection.15.11.2}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.3}Options}{52}{subsection.15.11.3}}
-\newlabel{man/pcp:options}{{15.11.3}{52}{Options}{subsection.15.11.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.4}Exit Status}{52}{subsection.15.11.4}}
-\newlabel{man/pcp:exit-status}{{15.11.4}{52}{Exit Status}{subsection.15.11.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.5}See Also}{52}{subsection.15.11.5}}
-\newlabel{man/pcp:see-also}{{15.11.5}{52}{See Also}{subsection.15.11.5}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {15.12}The \textbf {expire\_backups} command}{52}{section.15.12}}
-\newlabel{man/expire_backups::doc}{{15.12}{52}{The \textbf {expire\_backups} command}{section.15.12}{}}
-\newlabel{man/expire_backups:the-expire-backups-command}{{15.12}{52}{The \textbf {expire\_backups} command}{section.15.12}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.1}Synopsis}{52}{subsection.15.12.1}}
-\newlabel{man/expire_backups:synopsis}{{15.12.1}{52}{Synopsis}{subsection.15.12.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.2}Description}{52}{subsection.15.12.2}}
-\newlabel{man/expire_backups:description}{{15.12.2}{52}{Description}{subsection.15.12.2}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.3}Options}{53}{subsection.15.12.3}}
-\newlabel{man/expire_backups:options}{{15.12.3}{53}{Options}{subsection.15.12.3}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.4}Exit Status}{53}{subsection.15.12.4}}
-\newlabel{man/expire_backups:exit-status}{{15.12.4}{53}{Exit Status}{subsection.15.12.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.5}See Also}{54}{subsection.15.12.5}}
-\newlabel{man/expire_backups:see-also}{{15.12.5}{54}{See Also}{subsection.15.12.5}{}}
-\@writefile{toc}{\contentsline {chapter}{\numberline {16}Further Resources / Getting Help}{55}{chapter.16}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.2}Description}{47}{subsection.15.5.2}}
+\newlabel{man/ctrl:description}{{15.5.2}{47}{Description}{subsection.15.5.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.3}Options}{47}{subsection.15.5.3}}
+\newlabel{man/ctrl:options}{{15.5.3}{47}{Options}{subsection.15.5.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.4}Exit Codes}{47}{subsection.15.5.4}}
+\newlabel{man/ctrl:exit-codes}{{15.5.4}{47}{Exit Codes}{subsection.15.5.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.5.5}See Also}{47}{subsection.15.5.5}}
+\newlabel{man/ctrl:see-also}{{15.5.5}{47}{See Also}{subsection.15.5.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.6}The \textbf {s3qlcp} command}{48}{section.15.6}}
+\newlabel{man/cp::doc}{{15.6}{48}{The \textbf {s3qlcp} command}{section.15.6}{}}
+\newlabel{man/cp:the-command-command}{{15.6}{48}{The \textbf {s3qlcp} command}{section.15.6}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.1}Synopsis}{48}{subsection.15.6.1}}
+\newlabel{man/cp:synopsis}{{15.6.1}{48}{Synopsis}{subsection.15.6.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.2}Description}{48}{subsection.15.6.2}}
+\newlabel{man/cp:description}{{15.6.2}{48}{Description}{subsection.15.6.2}{}}
+\@writefile{toc}{\contentsline {subsubsection}{Snapshotting vs Hardlinking}{48}{subsubsection*.3}}
+\newlabel{man/cp:snapshotting-vs-hardlinking}{{15.6.2}{48}{Snapshotting vs Hardlinking}{subsubsection*.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.3}Options}{48}{subsection.15.6.3}}
+\newlabel{man/cp:options}{{15.6.3}{48}{Options}{subsection.15.6.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.4}Exit Codes}{49}{subsection.15.6.4}}
+\newlabel{man/cp:exit-codes}{{15.6.4}{49}{Exit Codes}{subsection.15.6.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.6.5}See Also}{49}{subsection.15.6.5}}
+\newlabel{man/cp:see-also}{{15.6.5}{49}{See Also}{subsection.15.6.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.7}The \textbf {s3qlrm} command}{49}{section.15.7}}
+\newlabel{man/rm::doc}{{15.7}{49}{The \textbf {s3qlrm} command}{section.15.7}{}}
+\newlabel{man/rm:the-command-command}{{15.7}{49}{The \textbf {s3qlrm} command}{section.15.7}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.1}Synopsis}{49}{subsection.15.7.1}}
+\newlabel{man/rm:synopsis}{{15.7.1}{49}{Synopsis}{subsection.15.7.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.2}Description}{49}{subsection.15.7.2}}
+\newlabel{man/rm:description}{{15.7.2}{49}{Description}{subsection.15.7.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.3}Options}{49}{subsection.15.7.3}}
+\newlabel{man/rm:options}{{15.7.3}{49}{Options}{subsection.15.7.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.4}Exit Codes}{49}{subsection.15.7.4}}
+\newlabel{man/rm:exit-codes}{{15.7.4}{49}{Exit Codes}{subsection.15.7.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.7.5}See Also}{50}{subsection.15.7.5}}
+\newlabel{man/rm:see-also}{{15.7.5}{50}{See Also}{subsection.15.7.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.8}The \textbf {s3qllock} command}{50}{section.15.8}}
+\newlabel{man/lock::doc}{{15.8}{50}{The \textbf {s3qllock} command}{section.15.8}{}}
+\newlabel{man/lock:the-command-command}{{15.8}{50}{The \textbf {s3qllock} command}{section.15.8}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.1}Synopsis}{50}{subsection.15.8.1}}
+\newlabel{man/lock:synopsis}{{15.8.1}{50}{Synopsis}{subsection.15.8.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.2}Description}{50}{subsection.15.8.2}}
+\newlabel{man/lock:description}{{15.8.2}{50}{Description}{subsection.15.8.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.3}Rationale}{50}{subsection.15.8.3}}
+\newlabel{man/lock:rationale}{{15.8.3}{50}{Rationale}{subsection.15.8.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.4}Options}{50}{subsection.15.8.4}}
+\newlabel{man/lock:options}{{15.8.4}{50}{Options}{subsection.15.8.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.5}Exit Codes}{51}{subsection.15.8.5}}
+\newlabel{man/lock:exit-codes}{{15.8.5}{51}{Exit Codes}{subsection.15.8.5}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.8.6}See Also}{51}{subsection.15.8.6}}
+\newlabel{man/lock:see-also}{{15.8.6}{51}{See Also}{subsection.15.8.6}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.9}The \textbf {umount.s3ql} command}{51}{section.15.9}}
+\newlabel{man/umount::doc}{{15.9}{51}{The \textbf {umount.s3ql} command}{section.15.9}{}}
+\newlabel{man/umount:the-command-command}{{15.9}{51}{The \textbf {umount.s3ql} command}{section.15.9}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.1}Synopsis}{51}{subsection.15.9.1}}
+\newlabel{man/umount:synopsis}{{15.9.1}{51}{Synopsis}{subsection.15.9.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.2}Description}{51}{subsection.15.9.2}}
+\newlabel{man/umount:description}{{15.9.2}{51}{Description}{subsection.15.9.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.3}Options}{51}{subsection.15.9.3}}
+\newlabel{man/umount:options}{{15.9.3}{51}{Options}{subsection.15.9.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.4}Exit Codes}{52}{subsection.15.9.4}}
+\newlabel{man/umount:exit-codes}{{15.9.4}{52}{Exit Codes}{subsection.15.9.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.9.5}See Also}{52}{subsection.15.9.5}}
+\newlabel{man/umount:see-also}{{15.9.5}{52}{See Also}{subsection.15.9.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.10}The \textbf {fsck.s3ql} command}{52}{section.15.10}}
+\newlabel{man/fsck::doc}{{15.10}{52}{The \textbf {fsck.s3ql} command}{section.15.10}{}}
+\newlabel{man/fsck:the-command-command}{{15.10}{52}{The \textbf {fsck.s3ql} command}{section.15.10}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.1}Synopsis}{52}{subsection.15.10.1}}
+\newlabel{man/fsck:synopsis}{{15.10.1}{52}{Synopsis}{subsection.15.10.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.2}Description}{52}{subsection.15.10.2}}
+\newlabel{man/fsck:description}{{15.10.2}{52}{Description}{subsection.15.10.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.3}Options}{52}{subsection.15.10.3}}
+\newlabel{man/fsck:options}{{15.10.3}{52}{Options}{subsection.15.10.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.4}Exit Codes}{53}{subsection.15.10.4}}
+\newlabel{man/fsck:exit-codes}{{15.10.4}{53}{Exit Codes}{subsection.15.10.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.10.5}See Also}{53}{subsection.15.10.5}}
+\newlabel{man/fsck:see-also}{{15.10.5}{53}{See Also}{subsection.15.10.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.11}The \textbf {s3ql\_oauth\_client} command}{53}{section.15.11}}
+\newlabel{man/oauth_client::doc}{{15.11}{53}{The \textbf {s3ql\_oauth\_client} command}{section.15.11}{}}
+\newlabel{man/oauth_client:oauth-client}{{15.11}{53}{The \textbf {s3ql\_oauth\_client} command}{section.15.11}{}}
+\newlabel{man/oauth_client:the-command-command}{{15.11}{53}{The \textbf {s3ql\_oauth\_client} command}{section.15.11}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.1}Synopsis}{53}{subsection.15.11.1}}
+\newlabel{man/oauth_client:synopsis}{{15.11.1}{53}{Synopsis}{subsection.15.11.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.2}Description}{53}{subsection.15.11.2}}
+\newlabel{man/oauth_client:description}{{15.11.2}{53}{Description}{subsection.15.11.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.3}Options}{54}{subsection.15.11.3}}
+\newlabel{man/oauth_client:options}{{15.11.3}{54}{Options}{subsection.15.11.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.4}Exit Codes}{54}{subsection.15.11.4}}
+\newlabel{man/oauth_client:exit-codes}{{15.11.4}{54}{Exit Codes}{subsection.15.11.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.11.5}See Also}{54}{subsection.15.11.5}}
+\newlabel{man/oauth_client:see-also}{{15.11.5}{54}{See Also}{subsection.15.11.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.12}The \textbf {pcp} command}{54}{section.15.12}}
+\newlabel{man/pcp::doc}{{15.12}{54}{The \textbf {pcp} command}{section.15.12}{}}
+\newlabel{man/pcp:the-command-command}{{15.12}{54}{The \textbf {pcp} command}{section.15.12}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.1}Synopsis}{54}{subsection.15.12.1}}
+\newlabel{man/pcp:synopsis}{{15.12.1}{54}{Synopsis}{subsection.15.12.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.2}Description}{54}{subsection.15.12.2}}
+\newlabel{man/pcp:description}{{15.12.2}{54}{Description}{subsection.15.12.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.3}Options}{55}{subsection.15.12.3}}
+\newlabel{man/pcp:options}{{15.12.3}{55}{Options}{subsection.15.12.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.4}Exit Codes}{55}{subsection.15.12.4}}
+\newlabel{man/pcp:exit-codes}{{15.12.4}{55}{Exit Codes}{subsection.15.12.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.12.5}See Also}{55}{subsection.15.12.5}}
+\newlabel{man/pcp:see-also}{{15.12.5}{55}{See Also}{subsection.15.12.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {15.13}The \textbf {expire\_backups} command}{55}{section.15.13}}
+\newlabel{man/expire_backups::doc}{{15.13}{55}{The \textbf {expire\_backups} command}{section.15.13}{}}
+\newlabel{man/expire_backups:the-command-command}{{15.13}{55}{The \textbf {expire\_backups} command}{section.15.13}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.13.1}Synopsis}{55}{subsection.15.13.1}}
+\newlabel{man/expire_backups:synopsis}{{15.13.1}{55}{Synopsis}{subsection.15.13.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.13.2}Description}{55}{subsection.15.13.2}}
+\newlabel{man/expire_backups:description}{{15.13.2}{55}{Description}{subsection.15.13.2}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.13.3}Options}{56}{subsection.15.13.3}}
+\newlabel{man/expire_backups:options}{{15.13.3}{56}{Options}{subsection.15.13.3}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.13.4}Exit Codes}{56}{subsection.15.13.4}}
+\newlabel{man/expire_backups:exit-codes}{{15.13.4}{56}{Exit Codes}{subsection.15.13.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {15.13.5}See Also}{56}{subsection.15.13.5}}
+\newlabel{man/expire_backups:see-also}{{15.13.5}{56}{See Also}{subsection.15.13.5}{}}
+\@writefile{toc}{\contentsline {chapter}{\numberline {16}Further Resources / Getting Help}{57}{chapter.16}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
-\newlabel{resources::doc}{{16}{55}{Further Resources / Getting Help}{chapter.16}{}}
-\newlabel{resources:resources}{{16}{55}{Further Resources / Getting Help}{chapter.16}{}}
-\newlabel{resources:further-resources-getting-help}{{16}{55}{Further Resources / Getting Help}{chapter.16}{}}
-\@writefile{toc}{\contentsline {chapter}{\numberline {17}Implementation Details}{57}{chapter.17}}
+\newlabel{resources:resources}{{16}{57}{Further Resources / Getting Help}{chapter.16}{}}
+\newlabel{resources::doc}{{16}{57}{Further Resources / Getting Help}{chapter.16}{}}
+\newlabel{resources:further-resources-getting-help}{{16}{57}{Further Resources / Getting Help}{chapter.16}{}}
+\@writefile{toc}{\contentsline {chapter}{\numberline {17}Implementation Details}{59}{chapter.17}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
-\newlabel{impl_details::doc}{{17}{57}{Implementation Details}{chapter.17}{}}
-\newlabel{impl_details:implementation-details}{{17}{57}{Implementation Details}{chapter.17}{}}
-\newlabel{impl_details:impl-details}{{17}{57}{Implementation Details}{chapter.17}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {17.1}Metadata Storage}{57}{section.17.1}}
-\newlabel{impl_details:metadata-storage}{{17.1}{57}{Metadata Storage}{section.17.1}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {17.2}Data Storage}{57}{section.17.2}}
-\newlabel{impl_details:data-storage}{{17.2}{57}{Data Storage}{section.17.2}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {17.3}Data De-Duplication}{57}{section.17.3}}
-\newlabel{impl_details:data-de-duplication}{{17.3}{57}{Data De-Duplication}{section.17.3}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {17.4}Caching}{58}{section.17.4}}
-\newlabel{impl_details:caching}{{17.4}{58}{Caching}{section.17.4}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {17.5}Eventual Consistency Handling}{58}{section.17.5}}
-\newlabel{impl_details:eventual-consistency-handling}{{17.5}{58}{Eventual Consistency Handling}{section.17.5}{}}
-\@writefile{toc}{\contentsline {section}{\numberline {17.6}Encryption}{58}{section.17.6}}
-\newlabel{impl_details:encryption}{{17.6}{58}{Encryption}{section.17.6}{}}
+\newlabel{impl_details:implementation-details}{{17}{59}{Implementation Details}{chapter.17}{}}
+\newlabel{impl_details::doc}{{17}{59}{Implementation Details}{chapter.17}{}}
+\newlabel{impl_details:impl-details}{{17}{59}{Implementation Details}{chapter.17}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {17.1}Metadata Storage}{59}{section.17.1}}
+\newlabel{impl_details:metadata-storage}{{17.1}{59}{Metadata Storage}{section.17.1}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {17.2}Data Storage}{59}{section.17.2}}
+\newlabel{impl_details:data-storage}{{17.2}{59}{Data Storage}{section.17.2}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {17.3}Data De-Duplication}{59}{section.17.3}}
+\newlabel{impl_details:data-de-duplication}{{17.3}{59}{Data De-Duplication}{section.17.3}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {17.4}Caching}{60}{section.17.4}}
+\newlabel{impl_details:caching}{{17.4}{60}{Caching}{section.17.4}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {17.5}Eventual Consistency Handling}{60}{section.17.5}}
+\newlabel{impl_details:eventual-consistency-handling}{{17.5}{60}{Eventual Consistency Handling}{section.17.5}{}}
+\@writefile{toc}{\contentsline {section}{\numberline {17.6}Encryption}{60}{section.17.6}}
+\newlabel{impl_details:encryption}{{17.6}{60}{Encryption}{section.17.6}{}}
diff --git a/doc/latex/manual.log b/doc/latex/manual.log
deleted file mode 100644
index cfbc998..0000000
--- a/doc/latex/manual.log
+++ /dev/null
@@ -1,1261 +0,0 @@
-This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013/Debian) (format=pdflatex 2014.3.19) 29 MAR 2014 17:31
-entering extended mode
- restricted \write18 enabled.
- %&-line parsing enabled.
-**manual.tex
-(./manual.tex
-LaTeX2e <2011/06/27>
-Babel <3.9h> and hyphenation patterns for 7 languages loaded.
-(./sphinxmanual.cls
-Document Class: sphinxmanual 2009/06/02 Document class (Sphinx manual)
-(/usr/share/texlive/texmf-dist/tex/latex/base/report.cls
-Document Class: report 2007/10/19 v1.4h Standard LaTeX document class
-(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo
-File: size10.clo 2007/10/19 v1.4h Standard LaTeX file (size option)
-)
-\c@part=\count79
-\c@chapter=\count80
-\c@section=\count81
-\c@subsection=\count82
-\c@subsubsection=\count83
-\c@paragraph=\count84
-\c@subparagraph=\count85
-\c@figure=\count86
-\c@table=\count87
-\abovecaptionskip=\skip41
-\belowcaptionskip=\skip42
-\bibindent=\dimen102
-)) (/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty
-Package: inputenc 2008/03/30 v1.1d Input encoding file
-\inpenc@prehook=\toks14
-\inpenc@posthook=\toks15
-(/usr/share/texlive/texmf-dist/tex/latex/base/utf8.def
-File: utf8.def 2008/04/05 v1.1m UTF-8 support for inputenc
-Now handling font encoding OML ...
-... no UTF-8 mapping file for font encoding OML
-Now handling font encoding T1 ...
-... processing UTF-8 mapping file for font encoding T1
-(/usr/share/texlive/texmf-dist/tex/latex/base/t1enc.dfu
-File: t1enc.dfu 2008/04/05 v1.1m UTF-8 support for inputenc
- defining Unicode char U+00A1 (decimal 161)
- defining Unicode char U+00A3 (decimal 163)
- defining Unicode char U+00AB (decimal 171)
- defining Unicode char U+00BB (decimal 187)
- defining Unicode char U+00BF (decimal 191)
- defining Unicode char U+00C0 (decimal 192)
- defining Unicode char U+00C1 (decimal 193)
- defining Unicode char U+00C2 (decimal 194)
- defining Unicode char U+00C3 (decimal 195)
- defining Unicode char U+00C4 (decimal 196)
- defining Unicode char U+00C5 (decimal 197)
- defining Unicode char U+00C6 (decimal 198)
- defining Unicode char U+00C7 (decimal 199)
- defining Unicode char U+00C8 (decimal 200)
- defining Unicode char U+00C9 (decimal 201)
- defining Unicode char U+00CA (decimal 202)
- defining Unicode char U+00CB (decimal 203)
- defining Unicode char U+00CC (decimal 204)
- defining Unicode char U+00CD (decimal 205)
- defining Unicode char U+00CE (decimal 206)
- defining Unicode char U+00CF (decimal 207)
- defining Unicode char U+00D0 (decimal 208)
- defining Unicode char U+00D1 (decimal 209)
- defining Unicode char U+00D2 (decimal 210)
- defining Unicode char U+00D3 (decimal 211)
- defining Unicode char U+00D4 (decimal 212)
- defining Unicode char U+00D5 (decimal 213)
- defining Unicode char U+00D6 (decimal 214)
- defining Unicode char U+00D8 (decimal 216)
- defining Unicode char U+00D9 (decimal 217)
- defining Unicode char U+00DA (decimal 218)
- defining Unicode char U+00DB (decimal 219)
- defining Unicode char U+00DC (decimal 220)
- defining Unicode char U+00DD (decimal 221)
- defining Unicode char U+00DE (decimal 222)
- defining Unicode char U+00DF (decimal 223)
- defining Unicode char U+00E0 (decimal 224)
- defining Unicode char U+00E1 (decimal 225)
- defining Unicode char U+00E2 (decimal 226)
- defining Unicode char U+00E3 (decimal 227)
- defining Unicode char U+00E4 (decimal 228)
- defining Unicode char U+00E5 (decimal 229)
- defining Unicode char U+00E6 (decimal 230)
- defining Unicode char U+00E7 (decimal 231)
- defining Unicode char U+00E8 (decimal 232)
- defining Unicode char U+00E9 (decimal 233)
- defining Unicode char U+00EA (decimal 234)
- defining Unicode char U+00EB (decimal 235)
- defining Unicode char U+00EC (decimal 236)
- defining Unicode char U+00ED (decimal 237)
- defining Unicode char U+00EE (decimal 238)
- defining Unicode char U+00EF (decimal 239)
- defining Unicode char U+00F0 (decimal 240)
- defining Unicode char U+00F1 (decimal 241)
- defining Unicode char U+00F2 (decimal 242)
- defining Unicode char U+00F3 (decimal 243)
- defining Unicode char U+00F4 (decimal 244)
- defining Unicode char U+00F5 (decimal 245)
- defining Unicode char U+00F6 (decimal 246)
- defining Unicode char U+00F8 (decimal 248)
- defining Unicode char U+00F9 (decimal 249)
- defining Unicode char U+00FA (decimal 250)
- defining Unicode char U+00FB (decimal 251)
- defining Unicode char U+00FC (decimal 252)
- defining Unicode char U+00FD (decimal 253)
- defining Unicode char U+00FE (decimal 254)
- defining Unicode char U+00FF (decimal 255)
- defining Unicode char U+0102 (decimal 258)
- defining Unicode char U+0103 (decimal 259)
- defining Unicode char U+0104 (decimal 260)
- defining Unicode char U+0105 (decimal 261)
- defining Unicode char U+0106 (decimal 262)
- defining Unicode char U+0107 (decimal 263)
- defining Unicode char U+010C (decimal 268)
- defining Unicode char U+010D (decimal 269)
- defining Unicode char U+010E (decimal 270)
- defining Unicode char U+010F (decimal 271)
- defining Unicode char U+0110 (decimal 272)
- defining Unicode char U+0111 (decimal 273)
- defining Unicode char U+0118 (decimal 280)
- defining Unicode char U+0119 (decimal 281)
- defining Unicode char U+011A (decimal 282)
- defining Unicode char U+011B (decimal 283)
- defining Unicode char U+011E (decimal 286)
- defining Unicode char U+011F (decimal 287)
- defining Unicode char U+0130 (decimal 304)
- defining Unicode char U+0131 (decimal 305)
- defining Unicode char U+0132 (decimal 306)
- defining Unicode char U+0133 (decimal 307)
- defining Unicode char U+0139 (decimal 313)
- defining Unicode char U+013A (decimal 314)
- defining Unicode char U+013D (decimal 317)
- defining Unicode char U+013E (decimal 318)
- defining Unicode char U+0141 (decimal 321)
- defining Unicode char U+0142 (decimal 322)
- defining Unicode char U+0143 (decimal 323)
- defining Unicode char U+0144 (decimal 324)
- defining Unicode char U+0147 (decimal 327)
- defining Unicode char U+0148 (decimal 328)
- defining Unicode char U+014A (decimal 330)
- defining Unicode char U+014B (decimal 331)
- defining Unicode char U+0150 (decimal 336)
- defining Unicode char U+0151 (decimal 337)
- defining Unicode char U+0152 (decimal 338)
- defining Unicode char U+0153 (decimal 339)
- defining Unicode char U+0154 (decimal 340)
- defining Unicode char U+0155 (decimal 341)
- defining Unicode char U+0158 (decimal 344)
- defining Unicode char U+0159 (decimal 345)
- defining Unicode char U+015A (decimal 346)
- defining Unicode char U+015B (decimal 347)
- defining Unicode char U+015E (decimal 350)
- defining Unicode char U+015F (decimal 351)
- defining Unicode char U+0160 (decimal 352)
- defining Unicode char U+0161 (decimal 353)
- defining Unicode char U+0162 (decimal 354)
- defining Unicode char U+0163 (decimal 355)
- defining Unicode char U+0164 (decimal 356)
- defining Unicode char U+0165 (decimal 357)
- defining Unicode char U+016E (decimal 366)
- defining Unicode char U+016F (decimal 367)
- defining Unicode char U+0170 (decimal 368)
- defining Unicode char U+0171 (decimal 369)
- defining Unicode char U+0178 (decimal 376)
- defining Unicode char U+0179 (decimal 377)
- defining Unicode char U+017A (decimal 378)
- defining Unicode char U+017B (decimal 379)
- defining Unicode char U+017C (decimal 380)
- defining Unicode char U+017D (decimal 381)
- defining Unicode char U+017E (decimal 382)
- defining Unicode char U+200C (decimal 8204)
- defining Unicode char U+2013 (decimal 8211)
- defining Unicode char U+2014 (decimal 8212)
- defining Unicode char U+2018 (decimal 8216)
- defining Unicode char U+2019 (decimal 8217)
- defining Unicode char U+201A (decimal 8218)
- defining Unicode char U+201C (decimal 8220)
- defining Unicode char U+201D (decimal 8221)
- defining Unicode char U+201E (decimal 8222)
- defining Unicode char U+2030 (decimal 8240)
- defining Unicode char U+2031 (decimal 8241)
- defining Unicode char U+2039 (decimal 8249)
- defining Unicode char U+203A (decimal 8250)
- defining Unicode char U+2423 (decimal 9251)
-)
-Now handling font encoding OT1 ...
-... processing UTF-8 mapping file for font encoding OT1
-(/usr/share/texlive/texmf-dist/tex/latex/base/ot1enc.dfu
-File: ot1enc.dfu 2008/04/05 v1.1m UTF-8 support for inputenc
- defining Unicode char U+00A1 (decimal 161)
- defining Unicode char U+00A3 (decimal 163)
- defining Unicode char U+00B8 (decimal 184)
- defining Unicode char U+00BF (decimal 191)
- defining Unicode char U+00C5 (decimal 197)
- defining Unicode char U+00C6 (decimal 198)
- defining Unicode char U+00D8 (decimal 216)
- defining Unicode char U+00DF (decimal 223)
- defining Unicode char U+00E6 (decimal 230)
- defining Unicode char U+00EC (decimal 236)
- defining Unicode char U+00ED (decimal 237)
- defining Unicode char U+00EE (decimal 238)
- defining Unicode char U+00EF (decimal 239)
- defining Unicode char U+00F8 (decimal 248)
- defining Unicode char U+0131 (decimal 305)
- defining Unicode char U+0141 (decimal 321)
- defining Unicode char U+0142 (decimal 322)
- defining Unicode char U+0152 (decimal 338)
- defining Unicode char U+0153 (decimal 339)
- defining Unicode char U+2013 (decimal 8211)
- defining Unicode char U+2014 (decimal 8212)
- defining Unicode char U+2018 (decimal 8216)
- defining Unicode char U+2019 (decimal 8217)
- defining Unicode char U+201C (decimal 8220)
- defining Unicode char U+201D (decimal 8221)
-)
-Now handling font encoding OMS ...
-... processing UTF-8 mapping file for font encoding OMS
-(/usr/share/texlive/texmf-dist/tex/latex/base/omsenc.dfu
-File: omsenc.dfu 2008/04/05 v1.1m UTF-8 support for inputenc
- defining Unicode char U+00A7 (decimal 167)
- defining Unicode char U+00B6 (decimal 182)
- defining Unicode char U+00B7 (decimal 183)
- defining Unicode char U+2020 (decimal 8224)
- defining Unicode char U+2021 (decimal 8225)
- defining Unicode char U+2022 (decimal 8226)
-)
-Now handling font encoding OMX ...
-... no UTF-8 mapping file for font encoding OMX
-Now handling font encoding U ...
-... no UTF-8 mapping file for font encoding U
- defining Unicode char U+00A9 (decimal 169)
- defining Unicode char U+00AA (decimal 170)
- defining Unicode char U+00AE (decimal 174)
- defining Unicode char U+00BA (decimal 186)
- defining Unicode char U+02C6 (decimal 710)
- defining Unicode char U+02DC (decimal 732)
- defining Unicode char U+200C (decimal 8204)
- defining Unicode char U+2026 (decimal 8230)
- defining Unicode char U+2122 (decimal 8482)
- defining Unicode char U+2423 (decimal 9251)
-))
- defining Unicode char U+00A0 (decimal 160)
-(/usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty
-Package: cmap 2008/03/06 v1.0h CMap support: searchable PDF
-) (/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
-Package: fontenc 2005/09/27 v1.99g Standard LaTeX package
-(/usr/share/texlive/texmf-dist/tex/latex/base/t1enc.def
-File: t1enc.def 2005/09/27 v1.99g Standard LaTeX file
-LaTeX Font Info: Redeclaring font encoding T1 on input line 43.
-)<<t1.cmap>>) (/usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty
-Package: babel 2013/12/03 3.9h The Babel package
-(/usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf
-Language: english 2012/08/20 v3.3p English support from the babel system
-(/usr/share/texlive/texmf-dist/tex/generic/babel/babel.def
-File: babel.def 2013/12/03 3.9h Babel common definitions
-\babel@savecnt=\count88
-\U@D=\dimen103
-)
-\l@british = a dialect from \language\l@english
-\l@UKenglish = a dialect from \language\l@english
-\l@canadian = a dialect from \language\l@american
-\l@australian = a dialect from \language\l@british
-\l@newzealand = a dialect from \language\l@british
-)) (/usr/share/texlive/texmf-dist/tex/latex/psnfss/times.sty
-Package: times 2005/04/12 PSNFSS-v9.2a (SPQR)
-) (./fncychap.sty
-Package: fncychap 2007/07/30 v1.34 LaTeX package (Revised chapters)
-\RW=\skip43
-\mylen=\skip44
-\myhi=\skip45
-\px=\skip46
-\py=\skip47
-\pyy=\skip48
-\pxx=\skip49
-\c@AlphaCnt=\count89
-\c@AlphaDecCnt=\count90
-) (/usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty
-Package: longtable 2004/02/01 v4.11 Multi-page Table package (DPC)
-\LTleft=\skip50
-\LTright=\skip51
-\LTpre=\skip52
-\LTpost=\skip53
-\LTchunksize=\count91
-\LTcapwidth=\dimen104
-\LT@head=\box26
-\LT@firsthead=\box27
-\LT@foot=\box28
-\LT@lastfoot=\box29
-\LT@cols=\count92
-\LT@rows=\count93
-\c@LT@tables=\count94
-\c@LT@chunks=\count95
-\LT@p@ftn=\toks16
-) (./sphinx.sty
-Package: sphinx 2010/01/15 LaTeX package (Sphinx markup)
-(/usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty
-\fancy@headwidth=\skip54
-\f@ncyO@elh=\skip55
-\f@ncyO@erh=\skip56
-\f@ncyO@olh=\skip57
-\f@ncyO@orh=\skip58
-\f@ncyO@elf=\skip59
-\f@ncyO@erf=\skip60
-\f@ncyO@olf=\skip61
-\f@ncyO@orf=\skip62
-) (/usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty
-Package: textcomp 2005/09/27 v1.99g Standard LaTeX package
-Package textcomp Info: Sub-encoding information:
-(textcomp) 5 = only ISO-Adobe without \textcurrency
-(textcomp) 4 = 5 + \texteuro
-(textcomp) 3 = 4 + \textohm
-(textcomp) 2 = 3 + \textestimated + \textcurrency
-(textcomp) 1 = TS1 - \textcircled - \t
-(textcomp) 0 = TS1 (full)
-(textcomp) Font families with sub-encoding setting implement
-(textcomp) only a restricted character set as indicated.
-(textcomp) Family '?' is the default used for unknown fonts.
-(textcomp) See the documentation for details.
-Package textcomp Info: Setting ? sub-encoding to TS1/1 on input line 71.
-(/usr/share/texlive/texmf-dist/tex/latex/base/ts1enc.def
-File: ts1enc.def 2001/06/05 v3.0e (jk/car/fm) Standard LaTeX file
-Now handling font encoding TS1 ...
-... processing UTF-8 mapping file for font encoding TS1
-(/usr/share/texlive/texmf-dist/tex/latex/base/ts1enc.dfu
-File: ts1enc.dfu 2008/04/05 v1.1m UTF-8 support for inputenc
- defining Unicode char U+00A2 (decimal 162)
- defining Unicode char U+00A3 (decimal 163)
- defining Unicode char U+00A4 (decimal 164)
- defining Unicode char U+00A5 (decimal 165)
- defining Unicode char U+00A6 (decimal 166)
- defining Unicode char U+00A7 (decimal 167)
- defining Unicode char U+00A8 (decimal 168)
- defining Unicode char U+00A9 (decimal 169)
- defining Unicode char U+00AA (decimal 170)
- defining Unicode char U+00AC (decimal 172)
- defining Unicode char U+00AE (decimal 174)
- defining Unicode char U+00AF (decimal 175)
- defining Unicode char U+00B0 (decimal 176)
- defining Unicode char U+00B1 (decimal 177)
- defining Unicode char U+00B2 (decimal 178)
- defining Unicode char U+00B3 (decimal 179)
- defining Unicode char U+00B4 (decimal 180)
- defining Unicode char U+00B5 (decimal 181)
- defining Unicode char U+00B6 (decimal 182)
- defining Unicode char U+00B7 (decimal 183)
- defining Unicode char U+00B9 (decimal 185)
- defining Unicode char U+00BA (decimal 186)
- defining Unicode char U+00BC (decimal 188)
- defining Unicode char U+00BD (decimal 189)
- defining Unicode char U+00BE (decimal 190)
- defining Unicode char U+00D7 (decimal 215)
- defining Unicode char U+00F7 (decimal 247)
- defining Unicode char U+0192 (decimal 402)
- defining Unicode char U+02C7 (decimal 711)
- defining Unicode char U+02D8 (decimal 728)
- defining Unicode char U+02DD (decimal 733)
- defining Unicode char U+0E3F (decimal 3647)
- defining Unicode char U+2016 (decimal 8214)
- defining Unicode char U+2020 (decimal 8224)
- defining Unicode char U+2021 (decimal 8225)
- defining Unicode char U+2022 (decimal 8226)
- defining Unicode char U+2030 (decimal 8240)
- defining Unicode char U+2031 (decimal 8241)
- defining Unicode char U+203B (decimal 8251)
- defining Unicode char U+203D (decimal 8253)
- defining Unicode char U+2044 (decimal 8260)
- defining Unicode char U+204E (decimal 8270)
- defining Unicode char U+2052 (decimal 8274)
- defining Unicode char U+20A1 (decimal 8353)
- defining Unicode char U+20A4 (decimal 8356)
- defining Unicode char U+20A6 (decimal 8358)
- defining Unicode char U+20A9 (decimal 8361)
- defining Unicode char U+20AB (decimal 8363)
- defining Unicode char U+20AC (decimal 8364)
- defining Unicode char U+20B1 (decimal 8369)
- defining Unicode char U+2103 (decimal 8451)
- defining Unicode char U+2116 (decimal 8470)
- defining Unicode char U+2117 (decimal 8471)
- defining Unicode char U+211E (decimal 8478)
- defining Unicode char U+2120 (decimal 8480)
- defining Unicode char U+2122 (decimal 8482)
- defining Unicode char U+2126 (decimal 8486)
- defining Unicode char U+2127 (decimal 8487)
- defining Unicode char U+212E (decimal 8494)
- defining Unicode char U+2190 (decimal 8592)
- defining Unicode char U+2191 (decimal 8593)
- defining Unicode char U+2192 (decimal 8594)
- defining Unicode char U+2193 (decimal 8595)
- defining Unicode char U+2329 (decimal 9001)
- defining Unicode char U+232A (decimal 9002)
- defining Unicode char U+2422 (decimal 9250)
- defining Unicode char U+25E6 (decimal 9702)
- defining Unicode char U+25EF (decimal 9711)
- defining Unicode char U+266A (decimal 9834)
-))
-LaTeX Info: Redefining \oldstylenums on input line 266.
-Package textcomp Info: Setting cmr sub-encoding to TS1/0 on input line 281.
-Package textcomp Info: Setting cmss sub-encoding to TS1/0 on input line 282.
-Package textcomp Info: Setting cmtt sub-encoding to TS1/0 on input line 283.
-Package textcomp Info: Setting cmvtt sub-encoding to TS1/0 on input line 284.
-Package textcomp Info: Setting cmbr sub-encoding to TS1/0 on input line 285.
-Package textcomp Info: Setting cmtl sub-encoding to TS1/0 on input line 286.
-Package textcomp Info: Setting ccr sub-encoding to TS1/0 on input line 287.
-Package textcomp Info: Setting ptm sub-encoding to TS1/4 on input line 288.
-Package textcomp Info: Setting pcr sub-encoding to TS1/4 on input line 289.
-Package textcomp Info: Setting phv sub-encoding to TS1/4 on input line 290.
-Package textcomp Info: Setting ppl sub-encoding to TS1/3 on input line 291.
-Package textcomp Info: Setting pag sub-encoding to TS1/4 on input line 292.
-Package textcomp Info: Setting pbk sub-encoding to TS1/4 on input line 293.
-Package textcomp Info: Setting pnc sub-encoding to TS1/4 on input line 294.
-Package textcomp Info: Setting pzc sub-encoding to TS1/4 on input line 295.
-Package textcomp Info: Setting bch sub-encoding to TS1/4 on input line 296.
-Package textcomp Info: Setting put sub-encoding to TS1/5 on input line 297.
-Package textcomp Info: Setting uag sub-encoding to TS1/5 on input line 298.
-Package textcomp Info: Setting ugq sub-encoding to TS1/5 on input line 299.
-Package textcomp Info: Setting ul8 sub-encoding to TS1/4 on input line 300.
-Package textcomp Info: Setting ul9 sub-encoding to TS1/4 on input line 301.
-Package textcomp Info: Setting augie sub-encoding to TS1/5 on input line 302.
-Package textcomp Info: Setting dayrom sub-encoding to TS1/3 on input line 303.
-Package textcomp Info: Setting dayroms sub-encoding to TS1/3 on input line 304.
-
-Package textcomp Info: Setting pxr sub-encoding to TS1/0 on input line 305.
-Package textcomp Info: Setting pxss sub-encoding to TS1/0 on input line 306.
-Package textcomp Info: Setting pxtt sub-encoding to TS1/0 on input line 307.
-Package textcomp Info: Setting txr sub-encoding to TS1/0 on input line 308.
-Package textcomp Info: Setting txss sub-encoding to TS1/0 on input line 309.
-Package textcomp Info: Setting txtt sub-encoding to TS1/0 on input line 310.
-Package textcomp Info: Setting lmr sub-encoding to TS1/0 on input line 311.
-Package textcomp Info: Setting lmdh sub-encoding to TS1/0 on input line 312.
-Package textcomp Info: Setting lmss sub-encoding to TS1/0 on input line 313.
-Package textcomp Info: Setting lmssq sub-encoding to TS1/0 on input line 314.
-Package textcomp Info: Setting lmvtt sub-encoding to TS1/0 on input line 315.
-Package textcomp Info: Setting qhv sub-encoding to TS1/0 on input line 316.
-Package textcomp Info: Setting qag sub-encoding to TS1/0 on input line 317.
-Package textcomp Info: Setting qbk sub-encoding to TS1/0 on input line 318.
-Package textcomp Info: Setting qcr sub-encoding to TS1/0 on input line 319.
-Package textcomp Info: Setting qcs sub-encoding to TS1/0 on input line 320.
-Package textcomp Info: Setting qpl sub-encoding to TS1/0 on input line 321.
-Package textcomp Info: Setting qtm sub-encoding to TS1/0 on input line 322.
-Package textcomp Info: Setting qzc sub-encoding to TS1/0 on input line 323.
-Package textcomp Info: Setting qhvc sub-encoding to TS1/0 on input line 324.
-Package textcomp Info: Setting futs sub-encoding to TS1/4 on input line 325.
-Package textcomp Info: Setting futx sub-encoding to TS1/4 on input line 326.
-Package textcomp Info: Setting futj sub-encoding to TS1/4 on input line 327.
-Package textcomp Info: Setting hlh sub-encoding to TS1/3 on input line 328.
-Package textcomp Info: Setting hls sub-encoding to TS1/3 on input line 329.
-Package textcomp Info: Setting hlst sub-encoding to TS1/3 on input line 330.
-Package textcomp Info: Setting hlct sub-encoding to TS1/5 on input line 331.
-Package textcomp Info: Setting hlx sub-encoding to TS1/5 on input line 332.
-Package textcomp Info: Setting hlce sub-encoding to TS1/5 on input line 333.
-Package textcomp Info: Setting hlcn sub-encoding to TS1/5 on input line 334.
-Package textcomp Info: Setting hlcw sub-encoding to TS1/5 on input line 335.
-Package textcomp Info: Setting hlcf sub-encoding to TS1/5 on input line 336.
-Package textcomp Info: Setting pplx sub-encoding to TS1/3 on input line 337.
-Package textcomp Info: Setting pplj sub-encoding to TS1/3 on input line 338.
-Package textcomp Info: Setting ptmx sub-encoding to TS1/4 on input line 339.
-Package textcomp Info: Setting ptmj sub-encoding to TS1/4 on input line 340.
-) (/usr/share/texlive/texmf-dist/tex/latex/fancybox/fancybox.sty
-Package: fancybox 2010/05/15 1.4
-Style option: `fancybox' v1.4 <2010/05/15> (tvz)
-\@fancybox=\box30
-\shadowsize=\dimen105
-\@Sbox=\box31
-\do@VerbBox=\toks17
-\the@fancyput=\toks18
-\this@fancyput=\toks19
-\EndVerbatimTokens=\toks20
-\Verbatim@Outfile=\write3
-\Verbatim@Infile=\read1
-) (/usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty
-Package: titlesec 2011/12/15 v2.10.0 Sectioning titles
-\ttl@box=\box32
-\beforetitleunit=\skip63
-\aftertitleunit=\skip64
-\ttl@plus=\dimen106
-\ttl@minus=\dimen107
-\ttl@toksa=\toks21
-\titlewidth=\dimen108
-\titlewidthlast=\dimen109
-\titlewidthfirst=\dimen110
-) (./tabulary.sty
-Package: tabulary 2008/12/01 v0.9 tabulary package (DPC)
-(/usr/share/texlive/texmf-dist/tex/latex/tools/array.sty
-Package: array 2008/09/09 v2.4c Tabular extension package (FMi)
-\col@sep=\dimen111
-\extrarowheight=\dimen112
-\NC@list=\toks22
-\extratabsurround=\skip65
-\backup@length=\skip66
-)
-\TY@count=\count96
-\TY@linewidth=\dimen113
-\tymin=\dimen114
-\tymax=\dimen115
-\TY@tablewidth=\dimen116
-) (/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
-Package: amsmath 2013/01/14 v2.14 AMS math features
-\@mathmargin=\skip67
-For additional information on amsmath, use the `?' option.
-(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
-Package: amstext 2000/06/29 v2.01
-(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty
-File: amsgen.sty 1999/11/30 v2.0
-\@emptytoks=\toks23
-\ex@=\dimen117
-)) (/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty
-Package: amsbsy 1999/11/29 v1.2d
-\pmbraise@=\dimen118
-) (/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty
-Package: amsopn 1999/12/14 v2.01 operator names
-)
-\inf@bad=\count97
-LaTeX Info: Redefining \frac on input line 210.
-\uproot@=\count98
-\leftroot@=\count99
-LaTeX Info: Redefining \overline on input line 306.
-\classnum@=\count100
-\DOTSCASE@=\count101
-LaTeX Info: Redefining \ldots on input line 378.
-LaTeX Info: Redefining \dots on input line 381.
-LaTeX Info: Redefining \cdots on input line 466.
-\Mathstrutbox@=\box33
-\strutbox@=\box34
-\big@size=\dimen119
-LaTeX Font Info: Redeclaring font encoding OML on input line 566.
-LaTeX Font Info: Redeclaring font encoding OMS on input line 567.
-\macc@depth=\count102
-\c@MaxMatrixCols=\count103
-\dotsspace@=\muskip10
-\c@parentequation=\count104
-\dspbrk@lvl=\count105
-\tag@help=\toks24
-\row@=\count106
-\column@=\count107
-\maxfields@=\count108
-\andhelp@=\toks25
-\eqnshift@=\dimen120
-\alignsep@=\dimen121
-\tagshift@=\dimen122
-\tagwidth@=\dimen123
-\totwidth@=\dimen124
-\lineht@=\dimen125
-\@envbody=\toks26
-\multlinegap=\skip68
-\multlinetaggap=\skip69
-\mathdisplay@stack=\toks27
-LaTeX Info: Redefining \[ on input line 2665.
-LaTeX Info: Redefining \] on input line 2666.
-) (/usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty
-Package: makeidx 2000/03/29 v1.0m Standard LaTeX package
-) (/usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty
-Package: framed 2011/10/22 v 0.96: framed or shaded text with page breaks
-\OuterFrameSep=\skip70
-\fb@frw=\dimen126
-\fb@frh=\dimen127
-\FrameRule=\dimen128
-\FrameSep=\dimen129
-) (/usr/share/texlive/texmf-dist/tex/latex/base/ifthen.sty
-Package: ifthen 2001/05/26 v1.1c Standard LaTeX ifthen package (DPC)
-) (/usr/share/texlive/texmf-dist/tex/latex/graphics/color.sty
-Package: color 2005/11/14 v1.0j Standard LaTeX Color (DPC)
-(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/color.cfg
-File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive
-)
-Package color Info: Driver file: pdftex.def on input line 130.
-(/usr/share/texlive/texmf-dist/tex/latex/pdftex-def/pdftex.def
-File: pdftex.def 2011/05/27 v0.06d Graphics/color for pdfTeX
-(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/infwarerr.sty
-Package: infwarerr 2010/04/08 v1.3 Providing info/warning/error messages (HO)
-) (/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ltxcmds.sty
-Package: ltxcmds 2011/11/09 v1.22 LaTeX kernel commands for general use (HO)
-)
-\Gread@gobject=\count109
-)) (/usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty
-Package: fancyvrb 2008/02/07
-
-Style option: `fancyvrb' v2.7a, with DG/SPQR fixes, and firstline=lastline fix
-<2008/02/07> (tvz) (/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty
-Package: keyval 1999/03/16 v1.13 key=value parser (DPC)
-\KV@toks@=\toks28
-)
-\FV@CodeLineNo=\count110
-\FV@InFile=\read2
-\FV@TabBox=\box35
-\c@FancyVerbLine=\count111
-\FV@StepNumber=\count112
-\FV@OutFile=\write4
-) (/usr/share/texlive/texmf-dist/tex/latex/threeparttable/threeparttable.sty
-Package: threeparttable 2003/06/13 v 3.0
-\@tempboxb=\box36
-) (/usr/share/texlive/texmf-dist/tex/latex/mdwtools/footnote.sty
-Package: footnote 1997/01/28 1.13 Save footnotes around boxes
-\fn@notes=\box37
-\fn@width=\dimen130
-) (/usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty
-\wrapoverhang=\dimen131
-\WF@size=\dimen132
-\c@WF@wrappedlines=\count113
-\WF@box=\box38
-\WF@everypar=\toks29
-Package: wrapfig 2003/01/31 v 3.6
-) (/usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty
-Package: parskip 2001/04/09 non-zero parskip adjustments
-) (/usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty
-Package: alltt 1997/06/16 v2.0g defines alltt environment
-) (/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
-Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR)
-(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
-Package: graphics 2009/02/05 v1.0o Standard LaTeX Graphics (DPC,SPQR)
-(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty
-Package: trig 1999/03/16 v1.09 sin cos tan (DPC)
-) (/usr/share/texlive/texmf-dist/tex/latex/latexconfig/graphics.cfg
-File: graphics.cfg 2010/04/23 v1.9 graphics configuration of TeX Live
-)
-Package graphics Info: Driver file: pdftex.def on input line 91.
-)
-\Gin@req@height=\dimen133
-\Gin@req@width=\dimen134
-) (/usr/share/texlive/texmf-dist/tex/generic/pdftex/pdfcolor.tex)
-\distancetoright=\skip71
-\py@argswidth=\skip72
-\py@noticelength=\skip73
-\lineblockindentation=\skip74
-\image@box=\box39
-\image@width=\dimen135
-(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
-Package: hyperref 2012/11/06 v6.83m Hypertext links for LaTeX
-(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty
-Package: hobsub-hyperref 2012/05/28 v1.13 Bundle oberdiek, subset hyperref (HO)
-
-(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty
-Package: hobsub-generic 2012/05/28 v1.13 Bundle oberdiek, subset generic (HO)
-Package: hobsub 2012/05/28 v1.13 Construct package bundles (HO)
-Package hobsub Info: Skipping package `infwarerr' (already loaded).
-Package hobsub Info: Skipping package `ltxcmds' (already loaded).
-Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO)
-Package ifluatex Info: LuaTeX not detected.
-Package: ifvtex 2010/03/01 v1.5 Detect VTeX and its facilities (HO)
-Package ifvtex Info: VTeX not detected.
-Package: intcalc 2007/09/27 v1.1 Expandable calculations with integers (HO)
-Package: ifpdf 2011/01/30 v2.3 Provides the ifpdf switch (HO)
-Package ifpdf Info: pdfTeX in PDF mode is detected.
-Package: etexcmds 2011/02/16 v1.5 Avoid name clashes with e-TeX commands (HO)
-Package etexcmds Info: Could not find \expanded.
-(etexcmds) That can mean that you are not using pdfTeX 1.50 or
-(etexcmds) that some package has redefined \expanded.
-(etexcmds) In the latter case, load this package earlier.
-Package: kvsetkeys 2012/04/25 v1.16 Key value parser (HO)
-Package: kvdefinekeys 2011/04/07 v1.3 Define keys (HO)
-Package: pdftexcmds 2011/11/29 v0.20 Utility functions of pdfTeX for LuaTeX (HO
-)
-Package pdftexcmds Info: LuaTeX not detected.
-Package pdftexcmds Info: \pdf@primitive is available.
-Package pdftexcmds Info: \pdf@ifprimitive is available.
-Package pdftexcmds Info: \pdfdraftmode found.
-Package: pdfescape 2011/11/25 v1.13 Implements pdfTeX's escape features (HO)
-Package: bigintcalc 2012/04/08 v1.3 Expandable calculations on big integers (HO
-)
-Package: bitset 2011/01/30 v1.1 Handle bit-vector datatype (HO)
-Package: uniquecounter 2011/01/30 v1.2 Provide unlimited unique counter (HO)
-)
-Package hobsub Info: Skipping package `hobsub' (already loaded).
-Package: letltxmacro 2010/09/02 v1.4 Let assignment for LaTeX macros (HO)
-Package: hopatch 2012/05/28 v1.2 Wrapper for package hooks (HO)
-Package: xcolor-patch 2011/01/30 xcolor patch
-Package: atveryend 2011/06/30 v1.8 Hooks at the very end of document (HO)
-Package atveryend Info: \enddocument detected (standard20110627).
-Package: atbegshi 2011/10/05 v1.16 At begin shipout hook (HO)
-Package: refcount 2011/10/16 v3.4 Data extraction from label references (HO)
-Package: hycolor 2011/01/30 v1.7 Color options for hyperref/bookmark (HO)
-) (/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty
-Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional
-) (/usr/share/texlive/texmf-dist/tex/latex/oberdiek/auxhook.sty
-Package: auxhook 2011/03/04 v1.3 Hooks for auxiliary files (HO)
-) (/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty
-Package: kvoptions 2011/06/30 v3.11 Key value format for package options (HO)
-)
-\@linkdim=\dimen136
-\Hy@linkcounter=\count114
-\Hy@pagecounter=\count115
-(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def
-File: pd1enc.def 2012/11/06 v6.83m Hyperref: PDFDocEncoding definition (HO)
-Now handling font encoding PD1 ...
-... no UTF-8 mapping file for font encoding PD1
-)
-\Hy@SavedSpaceFactor=\count116
-(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/hyperref.cfg
-File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive
-)
-Package hyperref Info: Option `colorlinks' set `true' on input line 4319.
-Package hyperref Info: Option `breaklinks' set `true' on input line 4319.
-Package hyperref Info: Hyper figures OFF on input line 4443.
-Package hyperref Info: Link nesting OFF on input line 4448.
-Package hyperref Info: Hyper index ON on input line 4451.
-Package hyperref Info: Plain pages OFF on input line 4458.
-Package hyperref Info: Backreferencing OFF on input line 4463.
-Package hyperref Info: Implicit mode ON; LaTeX internals redefined.
-Package hyperref Info: Bookmarks ON on input line 4688.
-\c@Hy@tempcnt=\count117
-(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty
-\Urlmuskip=\muskip11
-Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
-)
-LaTeX Info: Redefining \url on input line 5041.
-\XeTeXLinkMargin=\dimen137
-\Fld@menulength=\count118
-\Field@Width=\dimen138
-\Fld@charsize=\dimen139
-Package hyperref Info: Hyper figures OFF on input line 6295.
-Package hyperref Info: Link nesting OFF on input line 6300.
-Package hyperref Info: Hyper index ON on input line 6303.
-Package hyperref Info: backreferencing OFF on input line 6310.
-Package hyperref Info: Link coloring ON on input line 6313.
-Package hyperref Info: Link coloring with OCG OFF on input line 6320.
-Package hyperref Info: PDF/A mode OFF on input line 6325.
-LaTeX Info: Redefining \ref on input line 6365.
-LaTeX Info: Redefining \pageref on input line 6369.
-\Hy@abspage=\count119
-\c@Item=\count120
-\c@Hfootnote=\count121
-)
-
-Package hyperref Message: Driver (autodetected): hpdftex.
-
-(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
-File: hpdftex.def 2012/11/06 v6.83m Hyperref driver for pdfTeX
-\Fld@listcount=\count122
-\c@bookmark@seq@number=\count123
-(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty
-Package: rerunfilecheck 2011/04/15 v1.7 Rerun checks for auxiliary files (HO)
-Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2
-82.
-)
-\Hy@SectionHShift=\skip75
-) (/usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty
-Package: hypcap 2011/02/16 v1.11 Adjusting the anchors of captions (HO)
-)
-\DUlineblockindent=\skip76
-) (/usr/share/texlive/texmf-dist/tex/latex/multirow/multirow.sty
-\bigstrutjot=\dimen140
-)
-\@indexfile=\write5
-\openout5 = `manual.idx'.
-
-Writing index file manual.idx
-(./manual.aux)
-\openout1 = `manual.aux'.
-
-LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 117.
-LaTeX Font Info: ... okay on input line 117.
-LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 117.
-LaTeX Font Info: ... okay on input line 117.
-LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 117.
-LaTeX Font Info: ... okay on input line 117.
-LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 117.
-LaTeX Font Info: ... okay on input line 117.
-LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 117.
-LaTeX Font Info: ... okay on input line 117.
-LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 117.
-LaTeX Font Info: ... okay on input line 117.
-LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 117.
-LaTeX Font Info: Try loading font information for TS1+cmr on input line 117.
-
-(/usr/share/texlive/texmf-dist/tex/latex/base/ts1cmr.fd
-File: ts1cmr.fd 1999/05/25 v2.5h Standard LaTeX font definitions
-)
-LaTeX Font Info: ... okay on input line 117.
-LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 117.
-LaTeX Font Info: ... okay on input line 117.
-LaTeX Font Info: Try loading font information for T1+ptm on input line 117.
-(/usr/share/texlive/texmf-dist/tex/latex/psnfss/t1ptm.fd
-File: t1ptm.fd 2001/06/04 font definitions for T1/ptm.
-) (/usr/share/texlive/texmf-dist/tex/context/base/supp-pdf.mkii
-[Loading MPS to PDF converter (version 2006.09.02).]
-\scratchcounter=\count124
-\scratchdimen=\dimen141
-\scratchbox=\box40
-\nofMPsegments=\count125
-\nofMParguments=\count126
-\everyMPshowfont=\toks30
-\MPscratchCnt=\count127
-\MPscratchDim=\dimen142
-\MPnumerator=\count128
-\makeMPintoPDFobject=\count129
-\everyMPtoPDFconversion=\toks31
-) (/usr/share/texlive/texmf-dist/tex/latex/oberdiek/epstopdf-base.sty
-Package: epstopdf-base 2010/02/09 v2.5 Base part for package epstopdf
-(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/grfext.sty
-Package: grfext 2010/08/19 v1.1 Manage graphics extensions (HO)
-)
-Package grfext Info: Graphics extension search list:
-(grfext) [.png,.pdf,.jpg,.mps,.jpeg,.jbig2,.jb2,.PNG,.PDF,.JPG,.JPE
-G,.JBIG2,.JB2,.eps]
-(grfext) \AppendGraphicsExtensions on input line 452.
-(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
-File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
-e
-))
-\AtBeginShipoutBox=\box41
-Package hyperref Info: Link coloring ON on input line 117.
-(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
-Package: nameref 2012/10/27 v2.43 Cross-referencing by name of section
-(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/gettitlestring.sty
-Package: gettitlestring 2010/12/03 v1.4 Cleanup title references (HO)
-)
-\c@section@level=\count130
-)
-LaTeX Info: Redefining \ref on input line 117.
-LaTeX Info: Redefining \pageref on input line 117.
-LaTeX Info: Redefining \nameref on input line 117.
-(./manual.out) (./manual.out)
-\@outlinefile=\write6
-\openout6 = `manual.out'.
-
-
-Underfull \hbox (badness 10000) in paragraph at lines 120--120
-
- []
-
-LaTeX Font Info: Try loading font information for T1+phv on input line 120.
-(/usr/share/texlive/texmf-dist/tex/latex/psnfss/t1phv.fd
-File: t1phv.fd 2001/06/04 scalable font definitions for T1/phv.
-)
-LaTeX Font Info: Font shape `T1/phv/bx/n' in size <24.88> not available
-(Font) Font shape `T1/phv/b/n' tried instead on input line 120.
-LaTeX Font Info: Font shape `T1/phv/m/it' in size <17.28> not available
-(Font) Font shape `T1/phv/m/sl' tried instead on input line 120.
-LaTeX Font Info: Font shape `T1/phv/bx/it' in size <17.28> not available
-(Font) Font shape `T1/phv/b/it' tried instead on input line 120.
-LaTeX Font Info: Font shape `T1/phv/b/it' in size <17.28> not available
-(Font) Font shape `T1/phv/b/sl' tried instead on input line 120.
-LaTeX Font Info: Font shape `T1/phv/bx/n' in size <17.28> not available
-(Font) Font shape `T1/phv/b/n' tried instead on input line 120.
-<<ot1.cmap>><<oml.cmap>><<oms.cmap>><<omx.cmap>> [1
-
-{/home/nikratio/.texmf-var/fonts/map/pdftex/updmap/pdftex.map
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/.notdef': font file present but not includ
-ed, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/Agrave': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/Egrave': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/Eth': font file present but not included,
-will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/Igrave': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/OE': font file present but not included, w
-ill be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/Ocircumflex': font file present but not in
-cluded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/Oslash': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/P': font file present but not included, wi
-ll be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/Udieresis': font file present but not incl
-uded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/X': font file present but not included, wi
-ll be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/acute': font file present but not included
-, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/adieresis': font file present but not incl
-uded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/agrave': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/at': font file present but not included, w
-ill be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/breve': font file present but not included
-, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/cedilla': font file present but not includ
-ed, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/circumflex': font file present but not inc
-luded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/currency': font file present but not inclu
-ded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/degree': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/dieresis': font file present but not inclu
-ded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/dollar': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/dotlessj': font file present but not inclu
-ded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/egrave': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/eight': font file present but not included
-, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/eth': font file present but not included,
-will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/exclamdown': font file present but not inc
-luded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/fraction': font file present but not inclu
-ded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/hyphen': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/igrave': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/ocircumflex': font file present but not in
-cluded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/oe': font file present but not included, w
-ill be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/ogonek': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/onequarter': font file present but not inc
-luded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/oslash': font file present but not include
-d, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/p': font file present but not included, wi
-ll be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/parenleft': font file present but not incl
-uded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/quotedblbase': font file present but not i
-ncluded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/quotedblright': font file present but not
-included, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/quoteleft': font file present but not incl
-uded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/space': font file present but not included
-, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/tilde': font file present but not included
-, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/udieresis': font file present but not incl
-uded, will be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/x': font file present but not included, wi
-ll be treated as font file not present
-
-
-pdfTeX warning: pdflatex (file /home/nikratio/.texmf-var/fonts/map/pdftex/updma
-p/pdftex.map): ambiguous entry for `/zero': font file present but not included,
- will be treated as font file not present
-}] [2
-
-] (./manual.toc
-LaTeX Font Info: Font shape `T1/ptm/bx/n' in size <10> not available
-(Font) Font shape `T1/ptm/b/n' tried instead on input line 2.
-LaTeX Font Info: Font shape `T1/phv/bx/n' in size <10> not available
-(Font) Font shape `T1/phv/b/n' tried instead on input line 41.
-[1
-
-])
-\tf@toc=\write7
-\openout7 = `manual.toc'.
-
-[2]
-Chapter 1.
-LaTeX Font Info: Font shape `T1/phv/bx/n' in size <14.4> not available
-(Font) Font shape `T1/phv/b/n' tried instead on input line 125.
-LaTeX Font Info: Font shape `T1/ptm/bx/n' in size <14.4> not available
-(Font) Font shape `T1/ptm/b/n' tried instead on input line 125.
-LaTeX Font Info: Font shape `T1/ptm/bx/n' in size <24.88> not available
-(Font) Font shape `T1/ptm/b/n' tried instead on input line 125.
-LaTeX Font Info: Try loading font information for TS1+ptm on input line 148.
-
-(/usr/share/texlive/texmf-dist/tex/latex/psnfss/ts1ptm.fd
-File: ts1ptm.fd 2001/06/04 font definitions for TS1/ptm.
-) [1
-
-
-] [2]
-Chapter 2.
-LaTeX Font Info: Try loading font information for T1+pcr on input line 270.
-(/usr/share/texlive/texmf-dist/tex/latex/psnfss/t1pcr.fd
-File: t1pcr.fd 2001/06/04 font definitions for T1/pcr.
-) [3
-
-]
-LaTeX Font Info: Font shape `T1/pcr/m/it' in size <9> not available
-(Font) Font shape `T1/pcr/m/sl' tried instead on input line 388.
-[4] [5] [6
-
-]
-Chapter 3.
-[7]
-LaTeX Font Info: Font shape `T1/phv/bx/n' in size <12> not available
-(Font) Font shape `T1/phv/b/n' tried instead on input line 510.
-[8] [9] [10
-
-]
-Chapter 4.
-[11] [12] [13] [14]
-Chapter 5.
-
-Underfull \hbox (badness 10000) in paragraph at lines 951--953
-[]\T1/ptm/m/n/10 Read au-then-ti-ca-tion cre-den-tials from this file (de-fault
-:
- []
-
-[15
-
-] [16
-
-]
-Chapter 6.
-
-Underfull \hbox (badness 10000) in paragraph at lines 1018--1020
-[]\T1/ptm/m/n/10 Read au-then-ti-ca-tion cre-den-tials from this file (de-fault
-:
- []
-
-[17]
-Underfull \hbox (badness 10000) in paragraph at lines 1096--1100
-
- []
-
-[18]
-Chapter 7.
-
-Underfull \hbox (badness 10000) in paragraph at lines 1129--1131
-[]\T1/ptm/m/n/10 Read au-then-ti-ca-tion cre-den-tials from this file (de-fault
-:
- []
-
-[19
-
-] [20] [21] [22]
-Chapter 8.
-[23
-
-] [24] [25] [26
-
-]
-Chapter 9.
-[27] [28
-
-]
-Chapter 10.
-
-Underfull \hbox (badness 10000) in paragraph at lines 1594--1596
-[]\T1/ptm/m/n/10 Read au-then-ti-ca-tion cre-den-tials from this file (de-fault
-:
- []
-
-[29] [30
-
-]
-Chapter 11.
-[31] [32
-
-]
-Chapter 12.
-[33]
-Underfull \hbox (badness 10000) in paragraph at lines 1807--1812
-[]\T1/ptm/b/n/10 expire_backups \T1/ptm/m/n/10 us-age is sim-ple. It re-quires
-back-ups to have names of the forms
- []
-
-[34] [35] [36
-
-]
-Chapter 13.
-[37] [38]
-Chapter 14.
-[39
-
-] [40]
-Chapter 15.
-
-Underfull \hbox (badness 10000) in paragraph at lines 2090--2092
-[]\T1/ptm/m/n/10 Read au-then-ti-ca-tion cre-den-tials from this file (de-fault
-:
- []
-
-[41
-
-]
-Underfull \hbox (badness 10000) in paragraph at lines 2176--2178
-[]\T1/ptm/m/n/10 Read au-then-ti-ca-tion cre-den-tials from this file (de-fault
-:
- []
-
-[42] [43]
-Underfull \hbox (badness 10000) in paragraph at lines 2262--2264
-[]\T1/ptm/m/n/10 Read au-then-ti-ca-tion cre-den-tials from this file (de-fault
-:
- []
-
-[44] [45] [46] [47] [48] [49] [50]
-Underfull \hbox (badness 10000) in paragraph at lines 2823--2825
-[]\T1/ptm/m/n/10 Read au-then-ti-ca-tion cre-den-tials from this file (de-fault
-:
- []
-
-[51] [52]
-Underfull \hbox (badness 10000) in paragraph at lines 2973--2978
-[]\T1/ptm/b/n/10 expire_backups \T1/ptm/m/n/10 us-age is sim-ple. It re-quires
-back-ups to have names of the forms
- []
-
-[53] [54]
-Chapter 16.
-[55
-
-] [56
-
-]
-Chapter 17.
-[57]
-No file manual.ind.
-Package atveryend Info: Empty hook `BeforeClearDocument' on input line 3195.
-[58]
-Package atveryend Info: Empty hook `AfterLastShipout' on input line 3195.
-(./manual.aux)
-Package atveryend Info: Executing hook `AtVeryEndDocument' on input line 3195.
-Package atveryend Info: Executing hook `AtEndAfterFileList' on input line 3195.
-
-Package rerunfilecheck Info: File `manual.out' has not changed.
-(rerunfilecheck) Checksum: 6737C73D1ADD055EA5907CCE12BB2E43;4605.
-Package atveryend Info: Empty hook `AtVeryVeryEnd' on input line 3195.
- )
-Here is how much of TeX's memory you used:
- 9558 strings out of 494976
- 133559 string characters out of 6179137
- 232547 words of memory out of 5000000
- 12298 multiletter control sequences out of 15000+600000
- 63061 words of font info for 68 fonts, out of 8000000 for 9000
- 15 hyphenation exceptions out of 8191
- 38i,12n,51p,258b,499s stack positions out of 5000i,500n,10000p,200000b,80000s
-{/usr/share/texlive/texmf-dist/fonts/enc/dvips/base/8r.enc}</usr/share/texliv
-e/texmf-dist/fonts/type1/urw/courier/ucrr8a.pfb></usr/share/texlive/texmf-dist/
-fonts/type1/urw/courier/ucrro8a.pfb></usr/share/texlive/texmf-dist/fonts/type1/
-urw/helvetic/uhvb8a.pfb></usr/share/texlive/texmf-dist/fonts/type1/urw/helvetic
-/uhvbo8a.pfb></usr/share/texlive/texmf-dist/fonts/type1/urw/helvetic/uhvr8a.pfb
-></usr/share/texlive/texmf-dist/fonts/type1/urw/times/utmb8a.pfb></usr/share/te
-xlive/texmf-dist/fonts/type1/urw/times/utmr8a.pfb></usr/share/texlive/texmf-dis
-t/fonts/type1/urw/times/utmri8a.pfb>
-Output written on manual.pdf (62 pages, 244822 bytes).
-PDF statistics:
- 919 PDF objects out of 1000 (max. 8388607)
- 833 compressed objects within 9 object streams
- 236 named destinations out of 1000 (max. 500000)
- 597 words of extra memory for PDF output out of 10000 (max. 10000000)
-
diff --git a/doc/latex/manual.out b/doc/latex/manual.out
index a2e8ba0..c90458c 100644
--- a/doc/latex/manual.out
+++ b/doc/latex/manual.out
@@ -60,13 +60,14 @@
\BOOKMARK [1][-]{section.15.8}{The s3qllock command}{chapter.15}% 60
\BOOKMARK [1][-]{section.15.9}{The umount.s3ql command}{chapter.15}% 61
\BOOKMARK [1][-]{section.15.10}{The fsck.s3ql command}{chapter.15}% 62
-\BOOKMARK [1][-]{section.15.11}{The pcp command}{chapter.15}% 63
-\BOOKMARK [1][-]{section.15.12}{The expire\137backups command}{chapter.15}% 64
-\BOOKMARK [0][-]{chapter.16}{Further Resources / Getting Help}{}% 65
-\BOOKMARK [0][-]{chapter.17}{Implementation Details}{}% 66
-\BOOKMARK [1][-]{section.17.1}{Metadata Storage}{chapter.17}% 67
-\BOOKMARK [1][-]{section.17.2}{Data Storage}{chapter.17}% 68
-\BOOKMARK [1][-]{section.17.3}{Data De-Duplication}{chapter.17}% 69
-\BOOKMARK [1][-]{section.17.4}{Caching}{chapter.17}% 70
-\BOOKMARK [1][-]{section.17.5}{Eventual Consistency Handling}{chapter.17}% 71
-\BOOKMARK [1][-]{section.17.6}{Encryption}{chapter.17}% 72
+\BOOKMARK [1][-]{section.15.11}{The s3ql\137oauth\137client command}{chapter.15}% 63
+\BOOKMARK [1][-]{section.15.12}{The pcp command}{chapter.15}% 64
+\BOOKMARK [1][-]{section.15.13}{The expire\137backups command}{chapter.15}% 65
+\BOOKMARK [0][-]{chapter.16}{Further Resources / Getting Help}{}% 66
+\BOOKMARK [0][-]{chapter.17}{Implementation Details}{}% 67
+\BOOKMARK [1][-]{section.17.1}{Metadata Storage}{chapter.17}% 68
+\BOOKMARK [1][-]{section.17.2}{Data Storage}{chapter.17}% 69
+\BOOKMARK [1][-]{section.17.3}{Data De-Duplication}{chapter.17}% 70
+\BOOKMARK [1][-]{section.17.4}{Caching}{chapter.17}% 71
+\BOOKMARK [1][-]{section.17.5}{Eventual Consistency Handling}{chapter.17}% 72
+\BOOKMARK [1][-]{section.17.6}{Encryption}{chapter.17}% 73
diff --git a/doc/latex/manual.tex b/doc/latex/manual.tex
index 64974c2..2b34d01 100644
--- a/doc/latex/manual.tex
+++ b/doc/latex/manual.tex
@@ -14,8 +14,8 @@
\title{S3QL Documentation}
-\date{March 29, 2014}
-\release{2.8.1}
+\date{June 28, 2014}
+\release{2.9}
\author{Nikolaus Rath}
\newcommand{\sphinxlogo}{}
\renewcommand{\releasename}{Release}
@@ -32,66 +32,66 @@
\PYG@it{\PYG@bf{\PYG@ff{#1}}}}}}}
\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+\PYG@do{#2}}
-\expandafter\def\csname PYG@tok@nt\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.47,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@s\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@nv\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.60,0.40,0.20}{##1}}}
-\expandafter\def\csname PYG@tok@w\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}}
-\expandafter\def\csname PYG@tok@vi\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.73}{##1}}}
-\expandafter\def\csname PYG@tok@vg\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.87,0.47,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@sc\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
-\expandafter\def\csname PYG@tok@vc\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.40,0.60}{##1}}}
-\expandafter\def\csname PYG@tok@c\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
-\expandafter\def\csname PYG@tok@ne\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@nf\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.40,0.73}{##1}}}
+\expandafter\def\csname PYG@tok@cm\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
+\expandafter\def\csname PYG@tok@mf\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.40,0.00,0.93}{##1}}}
+\expandafter\def\csname PYG@tok@gh\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
\expandafter\def\csname PYG@tok@na\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.80}{##1}}}
-\expandafter\def\csname PYG@tok@nb\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
-\expandafter\def\csname PYG@tok@nc\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.73,0.00,0.40}{##1}}}
-\expandafter\def\csname PYG@tok@k\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@nn\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.05,0.52,0.71}{##1}}}
\expandafter\def\csname PYG@tok@no\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.20,0.40}{##1}}}
-\expandafter\def\csname PYG@tok@o\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.20}{##1}}}
-\expandafter\def\csname PYG@tok@ni\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.53,0.00,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@m\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.40,0.00,0.93}{##1}}}
-\expandafter\def\csname PYG@tok@cs\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.80,0.00,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@il\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.87}{##1}}}
+\expandafter\def\csname PYG@tok@se\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
+\expandafter\def\csname PYG@tok@ss\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.67,0.40,0.00}{##1}}}
\expandafter\def\csname PYG@tok@cp\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.33,0.47,0.60}{##1}}}
-\expandafter\def\csname PYG@tok@kd\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@kn\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@kc\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@c\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
+\expandafter\def\csname PYG@tok@ow\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@bp\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
+\expandafter\def\csname PYG@tok@nd\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.33,0.33,0.33}{##1}}}
\expandafter\def\csname PYG@tok@gu\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.50,0.00,0.50}{##1}}}
-\expandafter\def\csname PYG@tok@gt\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
-\expandafter\def\csname PYG@tok@gs\endcsname{\let\PYG@bf=\textbf}
+\expandafter\def\csname PYG@tok@sr\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.00}{##1}}\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,1.00}{\strut ##1}}}
+\expandafter\def\csname PYG@tok@kd\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@il\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.87}{##1}}}
\expandafter\def\csname PYG@tok@err\endcsname{\def\PYG@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.67,0.67}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@nl\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.60,0.47,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@gp\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.78,0.36,0.04}{##1}}}
-\expandafter\def\csname PYG@tok@go\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
-\expandafter\def\csname PYG@tok@gi\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.63,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@gh\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
-\expandafter\def\csname PYG@tok@kr\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@vc\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.40,0.60}{##1}}}
\expandafter\def\csname PYG@tok@ge\endcsname{\let\PYG@it=\textit}
-\expandafter\def\csname PYG@tok@kp\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.20,0.53}{##1}}}
-\expandafter\def\csname PYG@tok@cm\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
-\expandafter\def\csname PYG@tok@kt\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.60}{##1}}}
-\expandafter\def\csname PYG@tok@ow\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@sb\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@se\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@sd\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.87,0.27,0.13}{##1}}}
+\expandafter\def\csname PYG@tok@mi\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.87}{##1}}}
\expandafter\def\csname PYG@tok@si\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{0.93,0.93,0.93}{\strut ##1}}}
+\expandafter\def\csname PYG@tok@o\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.20}{##1}}}
+\expandafter\def\csname PYG@tok@gd\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@gp\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.78,0.36,0.04}{##1}}}
+\expandafter\def\csname PYG@tok@m\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.40,0.00,0.93}{##1}}}
+\expandafter\def\csname PYG@tok@s1\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
+\expandafter\def\csname PYG@tok@kn\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
\expandafter\def\csname PYG@tok@sh\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@ss\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.67,0.40,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@vg\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.87,0.47,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@ni\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.53,0.00,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@s2\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
+\expandafter\def\csname PYG@tok@nv\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.60,0.40,0.20}{##1}}}
+\expandafter\def\csname PYG@tok@sc\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
+\expandafter\def\csname PYG@tok@k\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@cs\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.80,0.00,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@nf\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.40,0.73}{##1}}}
\expandafter\def\csname PYG@tok@mh\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.33,0.53}{##1}}}
+\expandafter\def\csname PYG@tok@s\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
+\expandafter\def\csname PYG@tok@go\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
+\expandafter\def\csname PYG@tok@kc\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@sd\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.87,0.27,0.13}{##1}}}
+\expandafter\def\csname PYG@tok@w\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}}
+\expandafter\def\csname PYG@tok@kt\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.60}{##1}}}
+\expandafter\def\csname PYG@tok@nb\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
+\expandafter\def\csname PYG@tok@kp\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.20,0.53}{##1}}}
+\expandafter\def\csname PYG@tok@ne\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@nc\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.73,0.00,0.40}{##1}}}
+\expandafter\def\csname PYG@tok@sb\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
+\expandafter\def\csname PYG@tok@nn\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.05,0.52,0.71}{##1}}}
+\expandafter\def\csname PYG@tok@kr\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.53,0.00}{##1}}}
\expandafter\def\csname PYG@tok@mo\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.27,0.00,0.93}{##1}}}
+\expandafter\def\csname PYG@tok@gt\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
+\expandafter\def\csname PYG@tok@gr\endcsname{\def\PYG@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}}
\expandafter\def\csname PYG@tok@sx\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.87,0.13,0.00}{##1}}\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@mf\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.40,0.00,0.93}{##1}}}
-\expandafter\def\csname PYG@tok@bp\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
-\expandafter\def\csname PYG@tok@nd\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.33,0.33,0.33}{##1}}}
+\expandafter\def\csname PYG@tok@nt\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.47,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@nl\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.60,0.47,0.00}{##1}}}
\expandafter\def\csname PYG@tok@c1\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.53,0.53,0.53}{##1}}}
-\expandafter\def\csname PYG@tok@gd\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}}
-\expandafter\def\csname PYG@tok@sr\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.00}{##1}}\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,1.00}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@s1\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@mi\endcsname{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.87}{##1}}}
-\expandafter\def\csname PYG@tok@s2\endcsname{\def\PYG@bc##1{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}
-\expandafter\def\csname PYG@tok@gr\endcsname{\def\PYG@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@vi\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.73}{##1}}}
+\expandafter\def\csname PYG@tok@gi\endcsname{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.63,0.00}{##1}}}
+\expandafter\def\csname PYG@tok@gs\endcsname{\let\PYG@bf=\textbf}
\def\PYGZbs{\char`\\}
\def\PYGZus{\char`\_}
@@ -123,7 +123,7 @@
\chapter{About S3QL}
-\label{about::doc}\label{about:s3ql-user-s-guide}\label{about:about-s3ql}
+\label{about:about-s3ql}\label{about::doc}\label{about:s3ql-user-s-guide}
S3QL is a file system that stores all its data online using storage
services like \href{http://code.google.com/apis/storage/}{Google Storage}, \href{http://aws.amazon.com/s3}{Amazon S3}, or \href{http://openstack.org/projects/storage/}{OpenStack}. S3QL
effectively provides a hard disk of dynamic, infinite capacity that
@@ -221,7 +221,7 @@ features that are not available in the \emph{1.x} versions.
\chapter{Installation}
-\label{installation::doc}\label{installation:installation}
+\label{installation:installation}\label{installation::doc}
S3QL depends on several other programs and libraries that have to be
installed first. The best method to satisfy these dependencies depends
on your distribution. In some cases S3QL and all its dependencies can
@@ -242,7 +242,7 @@ recommended run the \emph{default} S3QL branch (with version numbers
\emph{2.x}). This branch is actively developed and has a number of new
features that are not available in the \emph{1.x} versions.
-The following instructions are for S3QL 2.8.1.
+The following instructions are for S3QL 2.9.
\section{Dependencies}
@@ -276,6 +276,15 @@ The \href{https://www.dlitz.net/software/pycrypto/}{PyCrypto Python Module}. To
module is installed, try to execute \code{python -c 'import Crypto'}.
\item {}
+The \href{https://pypi.python.org/pypi/defusedxml/}{Python defusedxml module}. To check if this
+module is installed, try to execute \code{python -c 'import defusedxml'}.
+
+\item {}
+If you want to use OAuth2 authentication with Google Storage, you
+need the \href{https://pypi.python.org/pypi/requests/}{Python requests module}. To check if this module
+is installed, try to execute \code{python -c 'import requests'}.
+
+\item {}
\href{http://www.sqlite.org/}{SQLite} version 3.7.0 or newer. SQLite
has to be installed as a \emph{shared library} with development headers.
@@ -299,7 +308,7 @@ need at least version 0.39.
The \href{https://bitbucket.org/nikratio/python-dugong/}{Python dugong module}. To check if this
module is installed, try to execute \code{python -c 'import dugong';
print(dugong.\_\_version\_\_)'}. This should print a version number. You
-need at least version 2.0.
+need at least version 3.1.
\end{itemize}
@@ -430,7 +439,7 @@ being skipped by passing the \code{-rs} argument to
\chapter{Storage Backends}
-\label{backends::doc}\label{backends:storage-backends}\label{backends:id1}\label{backends:py-test}
+\label{backends:py-test}\label{backends::doc}\label{backends:storage-backends}\label{backends:id1}
S3QL supports different \emph{backends} to store data at different service
providers and using different protocols. A \emph{storage url} specifies a
backend together with some backend-specific information and uniquely
@@ -454,31 +463,47 @@ storage service offered by Google. To use the Google Storage backend,
you need to have (or sign up for) a Google account, and then \href{http://code.google.com/apis/storage/docs/signup.html}{activate
Google Storage}
for your account. The account is free, you will pay only for the
-amount of storage and traffic that you actually use. Once you have
-created the account, make sure to \href{http://code.google.com/apis/storage/docs/reference/v1/apiversion1.html\#enabling}{activate legacy access}.
+amount of storage and traffic that you actually use. There are two
+ways to access Google storage:
+\begin{enumerate}
+\item {}
+Use S3-like authentication. To do this, first \href{https://developers.google.com/storage/docs/migrating\#defaultproj}{set a default
+project}.
+Then use the \href{https://code.google.com/apis/console/\#:storage:legacy}{key management tool} to
+retrieve your \emph{Google Storage developer access key} and \emph{Google
+Storage developer secret} and use that as backend login and backend
+password.
+
+\item {}
+Use OAuth2 authentication. In this case you need to use \code{oauth2}
+as the backend login, and a valid OAuth2 refresh token as the
+backend password. To obtain a refresh token, you can use the
+{\hyperref[man/oauth_client:oauth-client]{\emph{s3ql\_oauth\_client}}} program. It will instruct
+you to open a specific URL in your browser, enter a code and
+authenticate with your Google account. Once this procedure is
+complete, {\hyperref[man/oauth_client:oauth-client]{\emph{s3ql\_oauth\_client}}} will print out
+the refresh token. Note that you need to do this procedure only
+once, the refresh token will remain valid until you explicitly
+revoke it.
+
+\end{enumerate}
To create a Google Storage bucket, you can use e.g. the \href{https://sandbox.google.com/storage/}{Google
-Storage Manager}. The storage
-URL for accessing the bucket in S3QL is then
+Storage Manager}. The storage URL for accessing the bucket in S3QL is
+then
\begin{Verbatim}[commandchars=\\\{\}]
\PYG{l}{gs://}\PYG{n+nv}{\PYGZlt{}bucketname\PYGZgt{}}\PYG{l}{/}\PYG{n+nv}{\PYGZlt{}prefix\PYGZgt{}}
\end{Verbatim}
-Here \emph{bucketname} is the name of the bucket, and \emph{prefix} can be
-an arbitrary prefix that will be prepended to all object names used by
+Here \emph{bucketname} is the name of the bucket, and \emph{prefix} can be an
+arbitrary prefix that will be prepended to all object names used by
S3QL. This allows you to store several S3QL file systems in the same
Google Storage bucket.
-Note that the backend login and password for accessing your Google
-Storage bucket are not your Google account name and password, but the
-\emph{Google Storage developer access key} and \emph{Google Storage developer
-secret} that you can manage with the \href{https://code.google.com/apis/console/\#:storage:legacy}{Google Storage key management
-tool}.
-
\section{Amazon S3}
-\label{backends:amazon-s3}
+\label{backends:amazon-s3}\label{backends:google-storage-manager}
\href{http://aws.amazon.com/s3}{Amazon S3} is the online storage service
offered by \href{http://aws.amazon.com/}{Amazon Web Services (AWS)}. To
use the S3 backend, you first need to sign up for an AWS account. The
@@ -606,7 +631,7 @@ support.
\section{S3 compatible}
-\label{backends:s3-compatible}\label{backends:rackspace}
+\label{backends:rackspace}\label{backends:s3-compatible}
The S3 compatible backend allows S3QL to access any storage service
that uses the same protocol as Amazon S3. The storage URL has the form
@@ -645,7 +670,7 @@ storage url \code{local:///home/john/s3ql}.
\chapter{Important Rules to Avoid Losing Data}
-\label{durability:sshfs}\label{durability::doc}\label{durability:important-rules-to-avoid-losing-data}\label{durability:durability}
+\label{durability:durability}\label{durability::doc}\label{durability:sshfs}\label{durability:important-rules-to-avoid-losing-data}
Most S3QL backends store data in distributed storage systems. These
systems differ from a traditional, local hard disk in several
important ways. In order to avoid losing data, this section should be
@@ -1341,7 +1366,7 @@ mounted.
\label{special::doc}\label{special:advanced-s3ql-features}
\section{Snapshotting and Copy-on-Write}
-\label{special:s3qlcp}\label{special:snapshotting-and-copy-on-write}
+\label{special:snapshotting-and-copy-on-write}\label{special:s3qlcp}
The command \code{s3qlcp} can be used to duplicate a directory tree without
physically copying the file contents. This is made possible by the
data de-duplication feature of S3QL.
@@ -1436,7 +1461,7 @@ For a full list of available options, run \code{s3qlstat -{-}help}.
\section{Immutable Trees}
-\label{special:s3qllock}\label{special:immutable-trees}
+\label{special:immutable-trees}\label{special:s3qllock}
The command \textbf{s3qllock} can be used to make a directory tree
immutable. Immutable trees can no longer be changed in any way
whatsoever. You can not add new files or directories and you can not
@@ -1483,7 +1508,7 @@ changed after they have been made immutable.
\section{Fast Recursive Removal}
-\label{special:s3qlrm}\label{special:fast-recursive-removal}
+\label{special:fast-recursive-removal}\label{special:s3qlrm}
The \code{s3qlrm} command can be used to recursively delete files and
directories on an S3QL file system. Although \code{s3qlrm} is faster than
using e.g. \code{rm -r}, the main reason for its existence is that it
@@ -1530,7 +1555,7 @@ Trigger a metadata upload.
\chapter{Unmounting}
-\label{umount::doc}\label{umount:unmounting}
+\label{umount:unmounting}\label{umount::doc}
To unmount an S3QL file system, use the command:
\begin{Verbatim}[commandchars=\\\{\}]
@@ -1617,7 +1642,7 @@ Force checking even if file system is marked clean.
\chapter{Storing Authentication Information}
-\label{authinfo::doc}\label{authinfo:storing-authentication-information}\label{authinfo:authinfo}
+\label{authinfo::doc}\label{authinfo:authinfo}\label{authinfo:storing-authentication-information}
Normally, S3QL reads username and password for the backend as well as
an encryption passphrase for the file system from the terminal. Most
commands also accept an \code{-{-}authfile} parameter that can be
@@ -1684,7 +1709,7 @@ module}.
\chapter{Contributed Programs}
-\label{contrib::doc}\label{contrib:contributed-programs}
+\label{contrib:contributed-programs}\label{contrib::doc}
S3QL comes with a few contributed programs that are not part of the
core distribution (and are therefore not installed automatically by
default), but which may nevertheless be useful. These programs are in
@@ -1847,7 +1872,7 @@ start, and properly unmounts it when the system is shut down.
\label{tips::doc}\label{tips:tips-tricks}
\section{SSH Backend}
-\label{tips:ssh-backend}\label{tips:ssh-tipp}
+\label{tips:ssh-tipp}\label{tips:ssh-backend}
By combining S3QL's local backend with \href{http://fuse.sourceforge.net/sshfs.html}{sshfs}, it is possible to store an
S3QL file system on arbitrary SSH servers: first mount the remote
target directory into the local filesystem,
@@ -1888,7 +1913,7 @@ to zero).
\section{Improving copy performance}
-\label{tips:improving-copy-performance}\label{tips:copy-performance}
+\label{tips:copy-performance}\label{tips:improving-copy-performance}
\begin{notice}{note}{Note:}
The following applies only when copying data \textbf{from} an S3QL file
system, \textbf{not} when copying data \textbf{to} an S3QL file system.
@@ -2056,7 +2081,7 @@ here in the User's Guide.
\section{The \textbf{mkfs.s3ql} command}
-\label{man/mkfs::doc}\label{man/mkfs:the-mkfs-s3ql-command}
+\label{man/mkfs::doc}\label{man/mkfs:the-command-command}
\subsection{Synopsis}
\label{man/mkfs:synopsis}
@@ -2118,10 +2143,21 @@ Overwrite any existing data.
\end{quote}
-\subsection{Exit Status}
-\label{man/mkfs:exit-status}
-\textbf{mkfs.s3ql} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/mkfs:exit-codes}
+\textbf{mkfs.s3ql} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2134,7 +2170,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{s3qladm} command}
-\label{man/adm::doc}\label{man/adm:the-s3qladm-command}
+\label{man/adm::doc}\label{man/adm:the-command-command}
\subsection{Synopsis}
\label{man/adm:synopsis}
@@ -2212,10 +2248,24 @@ Interactively download backups of the file system metadata.
\end{description}
-\subsection{Exit Status}
-\label{man/adm:exit-status}
-\textbf{s3qladm} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/adm:exit-codes}
+\textbf{s3qladm} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\item[{10}] \leavevmode
+Could not open log file for writing.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2228,7 +2278,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{mount.s3ql} command}
-\label{man/mount::doc}\label{man/mount:the-mount-s3ql-command}
+\label{man/mount::doc}\label{man/mount:the-command-command}
\subsection{Synopsis}
\label{man/mount:synopsis}
@@ -2326,10 +2376,54 @@ system over NFS. (default: False)
\end{quote}
-\subsection{Exit Status}
-\label{man/mount:exit-status}
-\textbf{mount.s3ql} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/mount:exit-codes}
+\textbf{mount.s3ql} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\item[{10}] \leavevmode
+Could not open log file for writing.
+
+\item[{30}] \leavevmode
+File system was not unmounted cleanly.
+
+\item[{31}] \leavevmode
+File system appears to be mounted elsewhere.
+
+\item[{32}] \leavevmode
+Unsupported file system revision (too old).
+
+\item[{33}] \leavevmode
+Unsupported file system revision (too new).
+
+\item[{34}] \leavevmode
+Insufficient free nodes, need to run \textbf{fsck.s3ql}.
+
+\item[{35}] \leavevmode
+Attempted to mount read-only, this is not supported.
+
+\item[{36}] \leavevmode
+Mountpoint does not exist.
+
+\item[{37}] \leavevmode
+Not enough available file descriptors.
+
+\item[{38}] \leavevmode
+Unable to access backend / invalid storage URL.
+
+\item[{39}] \leavevmode
+Unable to bind file system to mountpoint.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2342,7 +2436,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{s3qlstat} command}
-\label{man/stat::doc}\label{man/stat:the-s3qlstat-command}
+\label{man/stat::doc}\label{man/stat:the-command-command}
\subsection{Synopsis}
\label{man/stat:synopsis}
@@ -2376,10 +2470,21 @@ just print program version and exit
\end{quote}
-\subsection{Exit Status}
-\label{man/stat:exit-status}
-\textbf{s3qlstat} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/stat:exit-codes}
+\textbf{s3qlstat} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2392,7 +2497,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{s3qlctrl} command}
-\label{man/ctrl::doc}\label{man/ctrl:the-s3qlctrl-command}
+\label{man/ctrl::doc}\label{man/ctrl:the-command-command}
\subsection{Synopsis}
\label{man/ctrl:synopsis}
@@ -2467,10 +2572,21 @@ Hint: run \code{s3qlctrl \textless{}action\textgreater{} -{-}help} to get help o
that the different actions take.
-\subsection{Exit Status}
-\label{man/ctrl:exit-status}
-\textbf{s3qlctrl} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/ctrl:exit-codes}
+\textbf{s3qlctrl} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2483,7 +2599,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{s3qlcp} command}
-\label{man/cp::doc}\label{man/cp:the-s3qlcp-command}
+\label{man/cp::doc}\label{man/cp:the-command-command}
\subsection{Synopsis}
\label{man/cp:synopsis}
@@ -2571,10 +2687,21 @@ just print program version and exit
\end{quote}
-\subsection{Exit Status}
-\label{man/cp:exit-status}
-\textbf{s3qlcp} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/cp:exit-codes}
+\textbf{s3qlcp} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2587,7 +2714,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{s3qlrm} command}
-\label{man/rm::doc}\label{man/rm:the-s3qlrm-command}
+\label{man/rm::doc}\label{man/rm:the-command-command}
\subsection{Synopsis}
\label{man/rm:synopsis}
@@ -2627,10 +2754,21 @@ just print program version and exit
\end{quote}
-\subsection{Exit Status}
-\label{man/rm:exit-status}
-\textbf{s3qlrm} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/rm:exit-codes}
+\textbf{s3qlrm} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2643,7 +2781,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{s3qllock} command}
-\label{man/lock::doc}\label{man/lock:the-s3qllock-command}
+\label{man/lock::doc}\label{man/lock:the-command-command}
\subsection{Synopsis}
\label{man/lock:synopsis}
@@ -2713,10 +2851,21 @@ just print program version and exit
\end{quote}
-\subsection{Exit Status}
-\label{man/lock:exit-status}
-\textbf{s3qllock} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/lock:exit-codes}
+\textbf{s3qllock} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2729,7 +2878,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{umount.s3ql} command}
-\label{man/umount::doc}\label{man/umount:the-umount-s3ql-command}
+\label{man/umount::doc}\label{man/umount:the-command-command}
\subsection{Synopsis}
\label{man/umount:synopsis}
@@ -2773,10 +2922,21 @@ background once all open files have been closed.
\end{quote}
-\subsection{Exit Status}
-\label{man/umount:exit-status}
-\textbf{umount.s3ql} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/umount:exit-codes}
+\textbf{umount.s3ql} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2789,7 +2949,7 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\section{The \textbf{fsck.s3ql} command}
-\label{man/fsck::doc}\label{man/fsck:the-fsck-s3ql-command}
+\label{man/fsck::doc}\label{man/fsck:the-command-command}
\subsection{Synopsis}
\label{man/fsck:synopsis}
@@ -2845,10 +3005,54 @@ Force checking even if file system is marked clean.
\end{quote}
-\subsection{Exit Status}
-\label{man/fsck:exit-status}
-\textbf{fsck.s3ql} returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\subsection{Exit Codes}
+\label{man/fsck:exit-codes}
+If \textbf{fsck.s3ql} found any errors, the exit code will be 128 plus one of
+the codes listed below. If no errors were found, the following exit
+codes are used:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\item[{10}] \leavevmode
+Could not open log file for writing.
+
+\item[{32}] \leavevmode
+Unsupported file system revision (too old).
+
+\item[{33}] \leavevmode
+Unsupported file system revision (too new).
+
+\item[{38}] \leavevmode
+Unable to access backend / invalid storage URL.
+
+\item[{40}] \leavevmode
+Cannot check mounted file system.
+
+\item[{41}] \leavevmode
+User input required, but running in batch mode.
+
+\item[{42}] \leavevmode
+File system check aborted by user.
+
+\item[{43}] \leavevmode
+Local metadata is corrupted.
+
+\item[{44}] \leavevmode
+Uncorrectable errors found.
+
+\item[{128}] \leavevmode
+This error code will be \emph{added} to one of the codes above if
+errors have been found.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2860,8 +3064,75 @@ system, common locations are \code{/usr/share/doc/s3ql} or
\code{/usr/local/doc/s3ql}.
+\section{The \textbf{s3ql\_oauth\_client} command}
+\label{man/oauth_client::doc}\label{man/oauth_client:oauth-client}\label{man/oauth_client:the-command-command}
+
+\subsection{Synopsis}
+\label{man/oauth_client:synopsis}
+\begin{Verbatim}[commandchars=\\\{\}]
+\PYG{l}{s3ql\PYGZus{}oauth\PYGZus{}client }\PYG{g+ge}{[options]}
+\end{Verbatim}
+
+
+\subsection{Description}
+\label{man/oauth_client:description}
+The \textbf{s3ql\_oauth\_client} command may be used to obtain OAuth2 authentication
+tokens for use with Google Storage. It requests ``user code'' from
+Google which has to be pasted into the browser to complete the
+authentication process interactively. Once authentication in the
+browser has been completed, \textbf{s3ql\_oauth\_client} displays the OAuth2 refresh
+token.
+
+When combined with the special username \code{oauth2}, the refresh token
+can be used as a backend passphrase when using the Google Storage S3QL
+backend.
+
+
+\subsection{Options}
+\label{man/oauth_client:options}
+The \textbf{s3ql\_oauth\_client} command accepts the following options:
+\begin{quote}
+\begin{optionlist}{3cm}
+\item [-{-}debug \textless{}module\textgreater{}]
+activate debugging output from \textless{}module\textgreater{}. Use \code{all} to get
+debug messages from all modules. This option can be
+specified multiple times.
+\item [-{-}quiet]
+be really quiet
+\item [-{-}version]
+just print program version and exit
+\end{optionlist}
+\end{quote}
+
+
+\subsection{Exit Codes}
+\label{man/oauth_client:exit-codes}
+\textbf{s3ql\_oauth\_client} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
+
+
+\subsection{See Also}
+\label{man/oauth_client:see-also}
+The S3QL homepage is at \href{https://bitbucket.org/nikratio/s3ql/}{https://bitbucket.org/nikratio/s3ql/}.
+
+The full S3QL documentation should also be installed somewhere on your
+system, common locations are \code{/usr/share/doc/s3ql} or
+\code{/usr/local/doc/s3ql}.
+
+
\section{The \textbf{pcp} command}
-\label{man/pcp::doc}\label{man/pcp:the-pcp-command}
+\label{man/pcp::doc}\label{man/pcp:the-command-command}
\subsection{Synopsis}
\label{man/pcp:synopsis}
@@ -2901,10 +3172,21 @@ Number of rsync processes to use (default: 10).
\end{quote}
-\subsection{Exit Status}
-\label{man/pcp:exit-status}
-\textbf{pcp} returns exit code 0 if the operation succeeded and 1 if some
-error occured.
+\subsection{Exit Codes}
+\label{man/pcp:exit-codes}
+\textbf{pcp} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -2913,7 +3195,7 @@ error occured.
\section{The \textbf{expire\_backups} command}
-\label{man/expire_backups::doc}\label{man/expire_backups:the-expire-backups-command}
+\label{man/expire_backups::doc}\label{man/expire_backups:the-command-command}
\subsection{Synopsis}
\label{man/expire_backups:synopsis}
@@ -3024,10 +3306,21 @@ Use \code{s3qlrm} command to delete backups.
\end{quote}
-\subsection{Exit Status}
-\label{man/expire_backups:exit-status}
-\textbf{expire\_backups} returns exit code 0 if the operation succeeded and 1 if some
-error occured.
+\subsection{Exit Codes}
+\label{man/expire_backups:exit-codes}
+\textbf{expire\_backups} may terminate with the following exit codes:
+\begin{quote}\begin{description}
+\item[{0}] \leavevmode
+Everything went well.
+
+\item[{1}] \leavevmode
+An unexpected error occured. This may indicate a bug in the
+program.
+
+\item[{2}] \leavevmode
+Invalid command line argument.
+
+\end{description}\end{quote}
\subsection{See Also}
@@ -3036,7 +3329,7 @@ error occured.
\chapter{Further Resources / Getting Help}
-\label{resources::doc}\label{resources:resources}\label{resources:further-resources-getting-help}
+\label{resources:resources}\label{resources::doc}\label{resources:further-resources-getting-help}
If you have questions or problems with S3QL that you weren't able to
resolve with this manual, you might want to consider the following other resources:
\begin{itemize}
@@ -3057,7 +3350,7 @@ Please report any bugs you may encounter in the \href{https://bitbucket.org/nikr
\chapter{Implementation Details}
-\label{impl_details::doc}\label{impl_details:implementation-details}\label{impl_details:impl-details}
+\label{impl_details:implementation-details}\label{impl_details::doc}\label{impl_details:impl-details}
This section provides some background information on how S3QL works
internally. Reading this section is not necessary to use S3QL.
diff --git a/doc/latex/manual.toc b/doc/latex/manual.toc
index 434bad7..81a2b29 100644
--- a/doc/latex/manual.toc
+++ b/doc/latex/manual.toc
@@ -12,7 +12,7 @@
\contentsline {section}{\numberline {3.2}Amazon S3}{7}{section.3.2}
\contentsline {subsection}{\numberline {3.2.1}Reduced Redundancy Storage (RRS)}{8}{subsection.3.2.1}
\contentsline {section}{\numberline {3.3}OpenStack/Swift}{8}{section.3.3}
-\contentsline {section}{\numberline {3.4}Rackspace CloudFiles}{8}{section.3.4}
+\contentsline {section}{\numberline {3.4}Rackspace CloudFiles}{9}{section.3.4}
\contentsline {section}{\numberline {3.5}S3 compatible}{9}{section.3.5}
\contentsline {section}{\numberline {3.6}Local}{9}{section.3.6}
\contentsline {chapter}{\numberline {4}Important Rules to Avoid Losing Data}{11}{chapter.4}
@@ -59,82 +59,88 @@
\contentsline {subsection}{\numberline {15.1.1}Synopsis}{41}{subsection.15.1.1}
\contentsline {subsection}{\numberline {15.1.2}Description}{41}{subsection.15.1.2}
\contentsline {subsection}{\numberline {15.1.3}Options}{41}{subsection.15.1.3}
-\contentsline {subsection}{\numberline {15.1.4}Exit Status}{42}{subsection.15.1.4}
+\contentsline {subsection}{\numberline {15.1.4}Exit Codes}{42}{subsection.15.1.4}
\contentsline {subsection}{\numberline {15.1.5}See Also}{42}{subsection.15.1.5}
\contentsline {section}{\numberline {15.2}The \textbf {s3qladm} command}{42}{section.15.2}
\contentsline {subsection}{\numberline {15.2.1}Synopsis}{42}{subsection.15.2.1}
\contentsline {subsection}{\numberline {15.2.2}Description}{42}{subsection.15.2.2}
\contentsline {subsection}{\numberline {15.2.3}Options}{42}{subsection.15.2.3}
\contentsline {subsection}{\numberline {15.2.4}Actions}{43}{subsection.15.2.4}
-\contentsline {subsection}{\numberline {15.2.5}Exit Status}{43}{subsection.15.2.5}
+\contentsline {subsection}{\numberline {15.2.5}Exit Codes}{43}{subsection.15.2.5}
\contentsline {subsection}{\numberline {15.2.6}See Also}{43}{subsection.15.2.6}
-\contentsline {section}{\numberline {15.3}The \textbf {mount.s3ql} command}{43}{section.15.3}
-\contentsline {subsection}{\numberline {15.3.1}Synopsis}{43}{subsection.15.3.1}
-\contentsline {subsection}{\numberline {15.3.2}Description}{43}{subsection.15.3.2}
+\contentsline {section}{\numberline {15.3}The \textbf {mount.s3ql} command}{44}{section.15.3}
+\contentsline {subsection}{\numberline {15.3.1}Synopsis}{44}{subsection.15.3.1}
+\contentsline {subsection}{\numberline {15.3.2}Description}{44}{subsection.15.3.2}
\contentsline {subsection}{\numberline {15.3.3}Options}{44}{subsection.15.3.3}
-\contentsline {subsection}{\numberline {15.3.4}Exit Status}{45}{subsection.15.3.4}
+\contentsline {subsection}{\numberline {15.3.4}Exit Codes}{45}{subsection.15.3.4}
\contentsline {subsection}{\numberline {15.3.5}See Also}{45}{subsection.15.3.5}
-\contentsline {section}{\numberline {15.4}The \textbf {s3qlstat} command}{45}{section.15.4}
-\contentsline {subsection}{\numberline {15.4.1}Synopsis}{45}{subsection.15.4.1}
-\contentsline {subsection}{\numberline {15.4.2}Description}{45}{subsection.15.4.2}
-\contentsline {subsection}{\numberline {15.4.3}Options}{45}{subsection.15.4.3}
-\contentsline {subsection}{\numberline {15.4.4}Exit Status}{45}{subsection.15.4.4}
-\contentsline {subsection}{\numberline {15.4.5}See Also}{45}{subsection.15.4.5}
+\contentsline {section}{\numberline {15.4}The \textbf {s3qlstat} command}{46}{section.15.4}
+\contentsline {subsection}{\numberline {15.4.1}Synopsis}{46}{subsection.15.4.1}
+\contentsline {subsection}{\numberline {15.4.2}Description}{46}{subsection.15.4.2}
+\contentsline {subsection}{\numberline {15.4.3}Options}{46}{subsection.15.4.3}
+\contentsline {subsection}{\numberline {15.4.4}Exit Codes}{46}{subsection.15.4.4}
+\contentsline {subsection}{\numberline {15.4.5}See Also}{46}{subsection.15.4.5}
\contentsline {section}{\numberline {15.5}The \textbf {s3qlctrl} command}{46}{section.15.5}
\contentsline {subsection}{\numberline {15.5.1}Synopsis}{46}{subsection.15.5.1}
-\contentsline {subsection}{\numberline {15.5.2}Description}{46}{subsection.15.5.2}
-\contentsline {subsection}{\numberline {15.5.3}Options}{46}{subsection.15.5.3}
-\contentsline {subsection}{\numberline {15.5.4}Exit Status}{46}{subsection.15.5.4}
-\contentsline {subsection}{\numberline {15.5.5}See Also}{46}{subsection.15.5.5}
-\contentsline {section}{\numberline {15.6}The \textbf {s3qlcp} command}{47}{section.15.6}
-\contentsline {subsection}{\numberline {15.6.1}Synopsis}{47}{subsection.15.6.1}
-\contentsline {subsection}{\numberline {15.6.2}Description}{47}{subsection.15.6.2}
-\contentsline {subsubsection}{Snapshotting vs Hardlinking}{47}{subsubsection*.3}
-\contentsline {subsection}{\numberline {15.6.3}Options}{47}{subsection.15.6.3}
-\contentsline {subsection}{\numberline {15.6.4}Exit Status}{48}{subsection.15.6.4}
-\contentsline {subsection}{\numberline {15.6.5}See Also}{48}{subsection.15.6.5}
-\contentsline {section}{\numberline {15.7}The \textbf {s3qlrm} command}{48}{section.15.7}
-\contentsline {subsection}{\numberline {15.7.1}Synopsis}{48}{subsection.15.7.1}
-\contentsline {subsection}{\numberline {15.7.2}Description}{48}{subsection.15.7.2}
-\contentsline {subsection}{\numberline {15.7.3}Options}{48}{subsection.15.7.3}
-\contentsline {subsection}{\numberline {15.7.4}Exit Status}{48}{subsection.15.7.4}
-\contentsline {subsection}{\numberline {15.7.5}See Also}{48}{subsection.15.7.5}
-\contentsline {section}{\numberline {15.8}The \textbf {s3qllock} command}{49}{section.15.8}
-\contentsline {subsection}{\numberline {15.8.1}Synopsis}{49}{subsection.15.8.1}
-\contentsline {subsection}{\numberline {15.8.2}Description}{49}{subsection.15.8.2}
-\contentsline {subsection}{\numberline {15.8.3}Rationale}{49}{subsection.15.8.3}
-\contentsline {subsection}{\numberline {15.8.4}Options}{49}{subsection.15.8.4}
-\contentsline {subsection}{\numberline {15.8.5}Exit Status}{49}{subsection.15.8.5}
-\contentsline {subsection}{\numberline {15.8.6}See Also}{50}{subsection.15.8.6}
-\contentsline {section}{\numberline {15.9}The \textbf {umount.s3ql} command}{50}{section.15.9}
-\contentsline {subsection}{\numberline {15.9.1}Synopsis}{50}{subsection.15.9.1}
-\contentsline {subsection}{\numberline {15.9.2}Description}{50}{subsection.15.9.2}
-\contentsline {subsection}{\numberline {15.9.3}Options}{50}{subsection.15.9.3}
-\contentsline {subsection}{\numberline {15.9.4}Exit Status}{50}{subsection.15.9.4}
-\contentsline {subsection}{\numberline {15.9.5}See Also}{50}{subsection.15.9.5}
-\contentsline {section}{\numberline {15.10}The \textbf {fsck.s3ql} command}{51}{section.15.10}
-\contentsline {subsection}{\numberline {15.10.1}Synopsis}{51}{subsection.15.10.1}
-\contentsline {subsection}{\numberline {15.10.2}Description}{51}{subsection.15.10.2}
-\contentsline {subsection}{\numberline {15.10.3}Options}{51}{subsection.15.10.3}
-\contentsline {subsection}{\numberline {15.10.4}Exit Status}{51}{subsection.15.10.4}
-\contentsline {subsection}{\numberline {15.10.5}See Also}{51}{subsection.15.10.5}
-\contentsline {section}{\numberline {15.11}The \textbf {pcp} command}{52}{section.15.11}
-\contentsline {subsection}{\numberline {15.11.1}Synopsis}{52}{subsection.15.11.1}
-\contentsline {subsection}{\numberline {15.11.2}Description}{52}{subsection.15.11.2}
-\contentsline {subsection}{\numberline {15.11.3}Options}{52}{subsection.15.11.3}
-\contentsline {subsection}{\numberline {15.11.4}Exit Status}{52}{subsection.15.11.4}
-\contentsline {subsection}{\numberline {15.11.5}See Also}{52}{subsection.15.11.5}
-\contentsline {section}{\numberline {15.12}The \textbf {expire\_backups} command}{52}{section.15.12}
-\contentsline {subsection}{\numberline {15.12.1}Synopsis}{52}{subsection.15.12.1}
-\contentsline {subsection}{\numberline {15.12.2}Description}{52}{subsection.15.12.2}
-\contentsline {subsection}{\numberline {15.12.3}Options}{53}{subsection.15.12.3}
-\contentsline {subsection}{\numberline {15.12.4}Exit Status}{53}{subsection.15.12.4}
-\contentsline {subsection}{\numberline {15.12.5}See Also}{54}{subsection.15.12.5}
-\contentsline {chapter}{\numberline {16}Further Resources / Getting Help}{55}{chapter.16}
-\contentsline {chapter}{\numberline {17}Implementation Details}{57}{chapter.17}
-\contentsline {section}{\numberline {17.1}Metadata Storage}{57}{section.17.1}
-\contentsline {section}{\numberline {17.2}Data Storage}{57}{section.17.2}
-\contentsline {section}{\numberline {17.3}Data De-Duplication}{57}{section.17.3}
-\contentsline {section}{\numberline {17.4}Caching}{58}{section.17.4}
-\contentsline {section}{\numberline {17.5}Eventual Consistency Handling}{58}{section.17.5}
-\contentsline {section}{\numberline {17.6}Encryption}{58}{section.17.6}
+\contentsline {subsection}{\numberline {15.5.2}Description}{47}{subsection.15.5.2}
+\contentsline {subsection}{\numberline {15.5.3}Options}{47}{subsection.15.5.3}
+\contentsline {subsection}{\numberline {15.5.4}Exit Codes}{47}{subsection.15.5.4}
+\contentsline {subsection}{\numberline {15.5.5}See Also}{47}{subsection.15.5.5}
+\contentsline {section}{\numberline {15.6}The \textbf {s3qlcp} command}{48}{section.15.6}
+\contentsline {subsection}{\numberline {15.6.1}Synopsis}{48}{subsection.15.6.1}
+\contentsline {subsection}{\numberline {15.6.2}Description}{48}{subsection.15.6.2}
+\contentsline {subsubsection}{Snapshotting vs Hardlinking}{48}{subsubsection*.3}
+\contentsline {subsection}{\numberline {15.6.3}Options}{48}{subsection.15.6.3}
+\contentsline {subsection}{\numberline {15.6.4}Exit Codes}{49}{subsection.15.6.4}
+\contentsline {subsection}{\numberline {15.6.5}See Also}{49}{subsection.15.6.5}
+\contentsline {section}{\numberline {15.7}The \textbf {s3qlrm} command}{49}{section.15.7}
+\contentsline {subsection}{\numberline {15.7.1}Synopsis}{49}{subsection.15.7.1}
+\contentsline {subsection}{\numberline {15.7.2}Description}{49}{subsection.15.7.2}
+\contentsline {subsection}{\numberline {15.7.3}Options}{49}{subsection.15.7.3}
+\contentsline {subsection}{\numberline {15.7.4}Exit Codes}{49}{subsection.15.7.4}
+\contentsline {subsection}{\numberline {15.7.5}See Also}{50}{subsection.15.7.5}
+\contentsline {section}{\numberline {15.8}The \textbf {s3qllock} command}{50}{section.15.8}
+\contentsline {subsection}{\numberline {15.8.1}Synopsis}{50}{subsection.15.8.1}
+\contentsline {subsection}{\numberline {15.8.2}Description}{50}{subsection.15.8.2}
+\contentsline {subsection}{\numberline {15.8.3}Rationale}{50}{subsection.15.8.3}
+\contentsline {subsection}{\numberline {15.8.4}Options}{50}{subsection.15.8.4}
+\contentsline {subsection}{\numberline {15.8.5}Exit Codes}{51}{subsection.15.8.5}
+\contentsline {subsection}{\numberline {15.8.6}See Also}{51}{subsection.15.8.6}
+\contentsline {section}{\numberline {15.9}The \textbf {umount.s3ql} command}{51}{section.15.9}
+\contentsline {subsection}{\numberline {15.9.1}Synopsis}{51}{subsection.15.9.1}
+\contentsline {subsection}{\numberline {15.9.2}Description}{51}{subsection.15.9.2}
+\contentsline {subsection}{\numberline {15.9.3}Options}{51}{subsection.15.9.3}
+\contentsline {subsection}{\numberline {15.9.4}Exit Codes}{52}{subsection.15.9.4}
+\contentsline {subsection}{\numberline {15.9.5}See Also}{52}{subsection.15.9.5}
+\contentsline {section}{\numberline {15.10}The \textbf {fsck.s3ql} command}{52}{section.15.10}
+\contentsline {subsection}{\numberline {15.10.1}Synopsis}{52}{subsection.15.10.1}
+\contentsline {subsection}{\numberline {15.10.2}Description}{52}{subsection.15.10.2}
+\contentsline {subsection}{\numberline {15.10.3}Options}{52}{subsection.15.10.3}
+\contentsline {subsection}{\numberline {15.10.4}Exit Codes}{53}{subsection.15.10.4}
+\contentsline {subsection}{\numberline {15.10.5}See Also}{53}{subsection.15.10.5}
+\contentsline {section}{\numberline {15.11}The \textbf {s3ql\_oauth\_client} command}{53}{section.15.11}
+\contentsline {subsection}{\numberline {15.11.1}Synopsis}{53}{subsection.15.11.1}
+\contentsline {subsection}{\numberline {15.11.2}Description}{53}{subsection.15.11.2}
+\contentsline {subsection}{\numberline {15.11.3}Options}{54}{subsection.15.11.3}
+\contentsline {subsection}{\numberline {15.11.4}Exit Codes}{54}{subsection.15.11.4}
+\contentsline {subsection}{\numberline {15.11.5}See Also}{54}{subsection.15.11.5}
+\contentsline {section}{\numberline {15.12}The \textbf {pcp} command}{54}{section.15.12}
+\contentsline {subsection}{\numberline {15.12.1}Synopsis}{54}{subsection.15.12.1}
+\contentsline {subsection}{\numberline {15.12.2}Description}{54}{subsection.15.12.2}
+\contentsline {subsection}{\numberline {15.12.3}Options}{55}{subsection.15.12.3}
+\contentsline {subsection}{\numberline {15.12.4}Exit Codes}{55}{subsection.15.12.4}
+\contentsline {subsection}{\numberline {15.12.5}See Also}{55}{subsection.15.12.5}
+\contentsline {section}{\numberline {15.13}The \textbf {expire\_backups} command}{55}{section.15.13}
+\contentsline {subsection}{\numberline {15.13.1}Synopsis}{55}{subsection.15.13.1}
+\contentsline {subsection}{\numberline {15.13.2}Description}{55}{subsection.15.13.2}
+\contentsline {subsection}{\numberline {15.13.3}Options}{56}{subsection.15.13.3}
+\contentsline {subsection}{\numberline {15.13.4}Exit Codes}{56}{subsection.15.13.4}
+\contentsline {subsection}{\numberline {15.13.5}See Also}{56}{subsection.15.13.5}
+\contentsline {chapter}{\numberline {16}Further Resources / Getting Help}{57}{chapter.16}
+\contentsline {chapter}{\numberline {17}Implementation Details}{59}{chapter.17}
+\contentsline {section}{\numberline {17.1}Metadata Storage}{59}{section.17.1}
+\contentsline {section}{\numberline {17.2}Data Storage}{59}{section.17.2}
+\contentsline {section}{\numberline {17.3}Data De-Duplication}{59}{section.17.3}
+\contentsline {section}{\numberline {17.4}Caching}{60}{section.17.4}
+\contentsline {section}{\numberline {17.5}Eventual Consistency Handling}{60}{section.17.5}
+\contentsline {section}{\numberline {17.6}Encryption}{60}{section.17.6}
diff --git a/doc/man/fsck.s3ql.1 b/doc/man/fsck.s3ql.1
index a822aef..b03b847 100644
--- a/doc/man/fsck.s3ql.1
+++ b/doc/man/fsck.s3ql.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "FSCK.S3QL" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "FSCK.S3QL" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
fsck.s3ql \- Check an S3QL file system for errors
.
@@ -100,10 +100,54 @@ Force checking even if file system is marked clean.
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBfsck.s3ql\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+If \fBfsck.s3ql\fP found any errors, the exit code will be 128 plus one of
+the codes listed below. If no errors were found, the following exit
+codes are used:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.TP
+.B 10
+Could not open log file for writing.
+.TP
+.B 32
+Unsupported file system revision (too old).
+.TP
+.B 33
+Unsupported file system revision (too new).
+.TP
+.B 38
+Unable to access backend / invalid storage URL.
+.TP
+.B 40
+Cannot check mounted file system.
+.TP
+.B 41
+User input required, but running in batch mode.
+.TP
+.B 42
+File system check aborted by user.
+.TP
+.B 43
+Local metadata is corrupted.
+.TP
+.B 44
+Uncorrectable errors found.
+.TP
+.B 128
+This error code will be \fIadded\fP to one of the codes above if
+errors have been found.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/mkfs.s3ql.1 b/doc/man/mkfs.s3ql.1
index a772c51..f76857a 100644
--- a/doc/man/mkfs.s3ql.1
+++ b/doc/man/mkfs.s3ql.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "MKFS.S3QL" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "MKFS.S3QL" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
mkfs.s3ql \- Create an S3QL file system
.
@@ -107,10 +107,21 @@ Overwrite any existing data.
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBmkfs.s3ql\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBmkfs.s3ql\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/mount.s3ql.1 b/doc/man/mount.s3ql.1
index 1e5eb3a..58ca7bf 100644
--- a/doc/man/mount.s3ql.1
+++ b/doc/man/mount.s3ql.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "MOUNT.S3QL" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "MOUNT.S3QL" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
mount.s3ql \- Mount an S3QL file system
.
@@ -152,10 +152,54 @@ system over NFS. (default: False)
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBmount.s3ql\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBmount.s3ql\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.TP
+.B 10
+Could not open log file for writing.
+.TP
+.B 30
+File system was not unmounted cleanly.
+.TP
+.B 31
+File system appears to be mounted elsewhere.
+.TP
+.B 32
+Unsupported file system revision (too old).
+.TP
+.B 33
+Unsupported file system revision (too new).
+.TP
+.B 34
+Insufficient free nodes, need to run \fBfsck.s3ql\fP\&.
+.TP
+.B 35
+Attempted to mount read\-only, this is not supported.
+.TP
+.B 36
+Mountpoint does not exist.
+.TP
+.B 37
+Not enough available file descriptors.
+.TP
+.B 38
+Unable to access backend / invalid storage URL.
+.TP
+.B 39
+Unable to bind file system to mountpoint.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/s3ql_oauth_client.1 b/doc/man/s3ql_oauth_client.1
new file mode 100644
index 0000000..ef1d7bc
--- /dev/null
+++ b/doc/man/s3ql_oauth_client.1
@@ -0,0 +1,105 @@
+.\" Man page generated from reStructuredText.
+.
+.TH "S3QL_OAUTH_CLIENT" "1" "June 28, 2014" "2.9" "S3QL"
+.SH NAME
+s3ql_oauth_client \- Obtain Google Storage OAuth2 tokens
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+s3ql_oauth_client [options]
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH DESCRIPTION
+.sp
+S3QL is a file system for online data storage. Before using S3QL, make
+sure to consult the full documentation (rather than just the man pages
+which only briefly document the available userspace commands).
+.sp
+The \fBs3ql_oauth_client\fP command may be used to obtain OAuth2 authentication
+tokens for use with Google Storage. It requests "user code" from
+Google which has to be pasted into the browser to complete the
+authentication process interactively. Once authentication in the
+browser has been completed, \fBs3ql_oauth_client\fP displays the OAuth2 refresh
+token.
+.sp
+When combined with the special username \fBoauth2\fP, the refresh token
+can be used as a backend passphrase when using the Google Storage S3QL
+backend.
+.SH OPTIONS
+.sp
+The \fBs3ql_oauth_client\fP command accepts the following options:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.TP
+.BI \-\-debug \ <module>
+activate debugging output from <module>. Use \fBall\fP to get
+debug messages from all modules. This option can be
+specified multiple times.
+.TP
+.B \-\-quiet
+be really quiet
+.TP
+.B \-\-version
+just print program version and exit
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH EXIT CODES
+.sp
+\fBs3ql_oauth_client\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
+.SH SEE ALSO
+.sp
+The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
+.sp
+The full S3QL documentation should also be installed somewhere on your
+system, common locations are \fB/usr/share/doc/s3ql\fP or
+\fB/usr/local/doc/s3ql\fP\&.
+.SH COPYRIGHT
+2008-2013, Nikolaus Rath
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/s3qladm.1 b/doc/man/s3qladm.1
index ba1de97..b311054 100644
--- a/doc/man/s3qladm.1
+++ b/doc/man/s3qladm.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "S3QLADM" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "S3QLADM" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
s3qladm \- Manage S3QL file systems
.
@@ -118,10 +118,24 @@ Delete the file system with all the stored data.
.B download\-metadata
Interactively download backups of the file system metadata.
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBs3qladm\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBs3qladm\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.TP
+.B 10
+Could not open log file for writing.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/s3qlcp.1 b/doc/man/s3qlcp.1
index a79659d..7b86eff 100644
--- a/doc/man/s3qlcp.1
+++ b/doc/man/s3qlcp.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "S3QLCP" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "S3QLCP" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
s3qlcp \- Copy-on-write replication on S3QL file systems
.
@@ -119,10 +119,21 @@ just print program version and exit
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBs3qlcp\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBs3qlcp\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/s3qlctrl.1 b/doc/man/s3qlctrl.1
index ec7123e..1618e98 100644
--- a/doc/man/s3qlctrl.1
+++ b/doc/man/s3qlctrl.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "S3QLCTRL" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "S3QLCTRL" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
s3qlctrl \- Control a mounted S3QL file system
.
@@ -124,10 +124,21 @@ just print program version and exit
.sp
Hint: run \fBs3qlctrl <action> \-\-help\fP to get help on the additional arguments
that the different actions take.
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBs3qlctrl\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBs3qlctrl\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/s3qllock.1 b/doc/man/s3qllock.1
index 9731d48..3f8d3b8 100644
--- a/doc/man/s3qllock.1
+++ b/doc/man/s3qllock.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "S3QLLOCK" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "S3QLLOCK" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
s3qllock \- Make trees on an S3QL file system immutable
.
@@ -105,10 +105,21 @@ just print program version and exit
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBs3qllock\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBs3qllock\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/s3qlrm.1 b/doc/man/s3qlrm.1
index e4395ec..0713117 100644
--- a/doc/man/s3qlrm.1
+++ b/doc/man/s3qlrm.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "S3QLRM" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "S3QLRM" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
s3qlrm \- Fast tree removal on S3QL file systems
.
@@ -77,10 +77,21 @@ just print program version and exit
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBs3qlrm\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBs3qlrm\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/s3qlstat.1 b/doc/man/s3qlstat.1
index 334e100..a2199c9 100644
--- a/doc/man/s3qlstat.1
+++ b/doc/man/s3qlstat.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "S3QLSTAT" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "S3QLSTAT" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
s3qlstat \- Gather S3QL file system statistics
.
@@ -71,10 +71,21 @@ just print program version and exit
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBs3qlstat\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBs3qlstat\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/man/umount.s3ql.1 b/doc/man/umount.s3ql.1
index c04a0d6..3e9a3a4 100644
--- a/doc/man/umount.s3ql.1
+++ b/doc/man/umount.s3ql.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH "UMOUNT.S3QL" "1" "March 29, 2014" "2.8.1" "S3QL"
+.TH "UMOUNT.S3QL" "1" "June 28, 2014" "2.9" "S3QL"
.SH NAME
umount.s3ql \- Unmount an S3QL file system
.
@@ -82,10 +82,21 @@ background once all open files have been closed.
.UNINDENT
.UNINDENT
.UNINDENT
-.SH EXIT STATUS
+.SH EXIT CODES
.sp
-\fBumount.s3ql\fP returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
+\fBumount.s3ql\fP may terminate with the following exit codes:
+.INDENT 0.0
+.TP
+.B 0
+Everything went well.
+.TP
+.B 1
+An unexpected error occured. This may indicate a bug in the
+program.
+.TP
+.B 2
+Invalid command line argument.
+.UNINDENT
.SH SEE ALSO
.sp
The S3QL homepage is at \fI\%https://bitbucket.org/nikratio/s3ql/\fP\&.
diff --git a/doc/manual.pdf b/doc/manual.pdf
index 7cef4e4..51ece1a 100644
--- a/doc/manual.pdf
+++ b/doc/manual.pdf
Binary files differ
diff --git a/rst/authinfo.rst b/rst/authinfo.rst
index da3122c..a8ebc9a 100644
--- a/rst/authinfo.rst
+++ b/rst/authinfo.rst
@@ -24,14 +24,14 @@ In each section, the following entries can be defined:
:backend-login:
Specifies the username to use for authentication with the backend.
-
+
:backend-password:
Specifies the password to use for authentication with the backend.
:fs-passphrase:
Specifies the passphrase to use to decrypt the file system (if
it is encrypted).
-
+
When reading the authentication file, S3QL considers every applicable
section in order and uses the last value that it found for each entry.
@@ -54,9 +54,9 @@ For example, consider the following authentication file::
storage-url: s3://joes-second-bucket/with-prefix
backend-login: bill
backend-password: bi23ll
- fs-passphrase: ll23bi
-
-With this authentication file, S3QL would try to log in as "joe"
+ fs-passphrase: ll23bi
+
+With this authentication file, S3QL would try to log in as "joe"
whenever the s3 backend is used, except when accessing a storage url
that begins with "s3://joes-second-bucket/with-prefix". In that case,
the last section becomes active and S3QL would use the "bill"
@@ -66,4 +66,3 @@ for storage urls that start with "s3://joes-first-bucket" or
The authentication file is parsed by the `Python ConfigParser
module <http://docs.python.org/library/configparser.html>`_.
-
diff --git a/rst/backends.rst b/rst/backends.rst
index 381fe35..159933a 100644
--- a/rst/backends.rst
+++ b/rst/backends.rst
@@ -29,27 +29,41 @@ storage service offered by Google. To use the Google Storage backend,
you need to have (or sign up for) a Google account, and then `activate
Google Storage <http://code.google.com/apis/storage/docs/signup.html>`_
for your account. The account is free, you will pay only for the
-amount of storage and traffic that you actually use. Once you have
-created the account, make sure to `activate legacy access
-<http://code.google.com/apis/storage/docs/reference/v1/apiversion1.html#enabling>`_.
+amount of storage and traffic that you actually use. There are two
+ways to access Google storage:
+
+#. Use S3-like authentication. To do this, first `set a default
+ project
+ <https://developers.google.com/storage/docs/migrating#defaultproj>`_.
+ Then use the `key management tool
+ <https://code.google.com/apis/console/#:storage:legacy>`_ to
+ retrieve your *Google Storage developer access key* and *Google
+ Storage developer secret* and use that as backend login and backend
+ password.
+
+#. Use OAuth2 authentication. In this case you need to use ``oauth2``
+ as the backend login, and a valid OAuth2 refresh token as the
+ backend password. To obtain a refresh token, you can use the
+ :ref:`s3ql_oauth_client <oauth_client>` program. It will instruct
+ you to open a specific URL in your browser, enter a code and
+ authenticate with your Google account. Once this procedure is
+ complete, :ref:`s3ql_oauth_client <oauth_client>` will print out
+ the refresh token. Note that you need to do this procedure only
+ once, the refresh token will remain valid until you explicitly
+ revoke it.
To create a Google Storage bucket, you can use e.g. the `Google
-Storage Manager <https://sandbox.google.com/storage/>`_. The storage
-URL for accessing the bucket in S3QL is then ::
+Storage Manager`_. The storage URL for accessing the bucket in S3QL is
+then ::
gs://<bucketname>/<prefix>
-Here *bucketname* is the name of the bucket, and *prefix* can be
-an arbitrary prefix that will be prepended to all object names used by
+Here *bucketname* is the name of the bucket, and *prefix* can be an
+arbitrary prefix that will be prepended to all object names used by
S3QL. This allows you to store several S3QL file systems in the same
Google Storage bucket.
-Note that the backend login and password for accessing your Google
-Storage bucket are not your Google account name and password, but the
-*Google Storage developer access key* and *Google Storage developer
-secret* that you can manage with the `Google Storage key management
-tool <https://code.google.com/apis/console/#:storage:legacy>`_.
-
+.. _`Google Storage Manager`: https://sandbox.google.com/storage/
Amazon S3
=========
@@ -207,7 +221,7 @@ mountpoint).
The storage URL for local storage is ::
local://<path>
-
+
Note that you have to write three consecutive slashes to specify an
absolute path, e.g. `local:///var/archive`. Also, relative paths will
automatically be converted to absolute paths before the authentication
diff --git a/rst/conf.py b/rst/conf.py
index ee24535..fc27fac 100644
--- a/rst/conf.py
+++ b/rst/conf.py
@@ -60,9 +60,9 @@ copyright = u'2008-2013, Nikolaus Rath'
# built documents.
#
# The short X.Y version.
-#version =
+#version =
# The full version, including alpha/beta/rc tags.
-#release =
+#release =
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -239,6 +239,6 @@ man_pages = [
None, 1),
('man/pcp', 'pcp', u'Recursive, parallel copy of directory trees',
None, 1),
+ ('man/oauth_client', 's3ql_oauth_client', u'Obtain Google Storage OAuth2 tokens',
+ None, 1),
]
-
-
diff --git a/rst/contrib.rst b/rst/contrib.rst
index c87a731..61d3488 100644
--- a/rst/contrib.rst
+++ b/rst/contrib.rst
@@ -86,4 +86,3 @@ s3ql_upstart.conf
``s3ql_upstart.conf`` is an example upstart job definition file. It
defines a job that automatically mounts an S3QL file system on system
start, and properly unmounts it when the system is shut down.
-
diff --git a/rst/durability.rst b/rst/durability.rst
index 1a2f331..9410a34 100644
--- a/rst/durability.rst
+++ b/rst/durability.rst
@@ -100,7 +100,7 @@ Of course, none of this is acceptable for a file system, and S3QL
generally handles any of the above situations internally so that it
always provides a fully consistent file system to the user. However,
there are some situations where an S3QL user nevertheless needs to be
-aware of the peculiarities of his chosen storage service.
+aware of the peculiarities of his chosen storage service.
Suppose that you mount the file system, store some new data, delete
some old data and unmount it. If you then mount the file system again
diff --git a/rst/impl_details.rst b/rst/impl_details.rst
index 7408417..8fb0160 100644
--- a/rst/impl_details.rst
+++ b/rst/impl_details.rst
@@ -28,10 +28,10 @@ the file system is unmounted. This has two implications:
fast because no data has to be send over the network.
#. An S3QL filesystem can only be mounted on one computer at a time,
- using a single :command:`mount.s3ql` process. Otherwise changes made in
+ using a single :program:`mount.s3ql` process. Otherwise changes made in
one mountpoint will invariably be overwritten when the second mount
point is unmounted.
-
+
Sockets, FIFOs and character devices do not need any additional
storage, all information about them is contained in the database.
@@ -109,7 +109,7 @@ marker object updated.
Encryption
==========
-When the file system is created, :command:`mkfs.s3ql` generates a 256 bit
+When the file system is created, :program:`mkfs.s3ql` generates a 256 bit
master key by reading from :file:`/dev/random`. The master key is
encrypted with the passphrase that is entered by the user, and then
stored with the rest of the file system data. Since the passphrase is
@@ -128,7 +128,7 @@ in the Python standard library.
Once the session key has been calculated, a SHA256 HMAC is calculated
over the data that is to be uploaded. Afterwards, the data is
compressed (unless :cmdopt:`--compress none` was passed to
-:command:`mount.s3ql`) and the HMAC inserted at the beginning. Both HMAC
+:program:`mount.s3ql`) and the HMAC inserted at the beginning. Both HMAC
and compressed data are then encrypted using 256 bit AES in CTR
mode using PyCrypto_. Finally, the nonce is
inserted in front of the encrypted data and HMAC, and the packet is
diff --git a/rst/include/about.rst b/rst/include/about.rst
index 27488e9..ade3bae 100644
--- a/rst/include/about.rst
+++ b/rst/include/about.rst
@@ -5,7 +5,3 @@
S3QL is a file system for online data storage. Before using S3QL, make
sure to consult the full documentation (rather than just the man pages
which only briefly document the available userspace commands).
-
-
-
-
diff --git a/rst/include/exitcodes.rst b/rst/include/exitcodes.rst
new file mode 100644
index 0000000..3875675
--- /dev/null
+++ b/rst/include/exitcodes.rst
@@ -0,0 +1,11 @@
+.. -*- mode: rst -*-
+
+:0:
+ Everything went well.
+
+:1:
+ An unexpected error occured. This may indicate a bug in the
+ program.
+
+:2:
+ Invalid command line argument.
diff --git a/rst/include/postman.rst b/rst/include/postman.rst
index 20ad8ba..20f3b71 100644
--- a/rst/include/postman.rst
+++ b/rst/include/postman.rst
@@ -1,13 +1,5 @@
.. -*- mode: rst -*-
-
-Exit Status
-===========
-
-|command| returns exit code 0 if the operation succeeded and 1 if some
-error occurred.
-
-
See Also
========
@@ -16,7 +8,3 @@ The S3QL homepage is at https://bitbucket.org/nikratio/s3ql/.
The full S3QL documentation should also be installed somewhere on your
system, common locations are :file:`/usr/share/doc/s3ql` or
:file:`/usr/local/doc/s3ql`.
-
-
-
-
diff --git a/rst/installation.rst b/rst/installation.rst
index e31c8db..08cda36 100644
--- a/rst/installation.rst
+++ b/rst/installation.rst
@@ -56,7 +56,16 @@ that is not the case.
* The `PyCrypto Python Module
<https://www.dlitz.net/software/pycrypto/>`_. To check if this
module is installed, try to execute `python -c 'import Crypto'`.
-
+
+* The `Python defusedxml module
+ <https://pypi.python.org/pypi/defusedxml/>`_. To check if this
+ module is installed, try to execute `python -c 'import defusedxml'`.
+
+* If you want to use OAuth2 authentication with Google Storage, you
+ need the `Python requests module
+ <https://pypi.python.org/pypi/requests/>`_. To check if this module
+ is installed, try to execute `python -c 'import requests'`.
+
* `SQLite <http://www.sqlite.org/>`_ version 3.7.0 or newer. SQLite
has to be installed as a *shared library* with development headers.
@@ -65,7 +74,7 @@ that is not the case.
python -c 'import apsw; print(apsw.apswversion())'
- The printed version number should be at least 3.7.0.
+ The printed version number should be at least 3.7.0.
* The `Python LLFUSE module
<http://code.google.com/p/python-llfuse/>`_. To check if this module
@@ -77,8 +86,8 @@ that is not the case.
<https://bitbucket.org/nikratio/python-dugong/>`_. To check if this
module is installed, try to execute `python -c 'import dugong';
print(dugong.__version__)'`. This should print a version number. You
- need at least version 2.0.
-
+ need at least version 3.1.
+
.. _inst-s3ql:
Installing S3QL
@@ -136,7 +145,7 @@ file. In that case, the build system will behave as it does for a
regular release.
The HTML and PDF documentation can be generated with ::
-
+
python3 setup.py build_sphinx
and S3QL can be installed as usual with ::
diff --git a/rst/issues.rst b/rst/issues.rst
index bc57e2f..8832399 100644
--- a/rst/issues.rst
+++ b/rst/issues.rst
@@ -44,7 +44,7 @@ Known Issues
* S3QL always updates file and directory access times as if the ``relatime``
mount option has been specified: the access time ("atime") is only updated
if it is currently earlier than either the status change time
- ("ctime") or modification time ("mtime").
+ ("ctime") or modification time ("mtime").
* S3QL directories always have an `st_nlink` value of 1. This may confuse
programs that rely on directories having `st_nlink` values of *(2 +
diff --git a/rst/man/adm.rst b/rst/man/adm.rst
index f87fc7c..f5d6ca9 100644
--- a/rst/man/adm.rst
+++ b/rst/man/adm.rst
@@ -1,8 +1,9 @@
.. -*- mode: rst -*-
-==============================
-The :program:`s3qladm` command
-==============================
+=====================
+The |command| command
+=====================
+
Synopsis
========
@@ -13,7 +14,7 @@ Synopsis
where :var:`action` may be either of :program:`passphrase`,
:program:`upgrade`, :program:`delete` or :program:`download-metadata`.
-
+
Description
===========
@@ -52,6 +53,17 @@ download-metadata
Interactively download backups of the file system metadata.
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
+
+:10:
+ Could not open log file for writing.
+
+
.. include:: ../include/postman.rst
.. |command| replace:: :program:`s3qladm`
diff --git a/rst/man/cp.rst b/rst/man/cp.rst
index a8f1306..4c49519 100644
--- a/rst/man/cp.rst
+++ b/rst/man/cp.rst
@@ -1,17 +1,17 @@
.. -*- mode: rst -*-
+=====================
+The |command| command
+=====================
-=================================
-The :program:`s3qlcp` command
-=================================
Synopsis
========
::
- s3qlcp [options] <source-dir> <dest-dir>
-
+ s3qlcp [options] <source-dir> <dest-dir>
+
Description
===========
@@ -75,7 +75,7 @@ any backup program.
.. end_main_content
-
+
Options
=======
@@ -86,8 +86,15 @@ The |command| command accepts the following options:
:start-after: show this help message and exit
-.. include:: ../include/postman.rst
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+.. include:: ../include/exitcodes.rst
+
+
+.. include:: ../include/postman.rst
-.. |command| replace:: :command:`s3qlcp`
+.. |command| replace:: :program:`s3qlcp`
diff --git a/rst/man/ctrl.rst b/rst/man/ctrl.rst
index 69c4487..9bf59dc 100644
--- a/rst/man/ctrl.rst
+++ b/rst/man/ctrl.rst
@@ -1,9 +1,9 @@
.. -*- mode: rst -*-
+=====================
+The |command| command
+=====================
-=================================
-The :program:`s3qlctrl` command
-=================================
Synopsis
========
@@ -15,7 +15,7 @@ Synopsis
where :var:`action` may be either of :program:`flushcache`,
:program:`upload-meta`, :program:`cachesize` or
:program:`log-metadata`.
-
+
Description
===========
@@ -41,11 +41,11 @@ cachesize
Changes the cache size of the file system. This action requires an
additional argument that specifies the new cache size in KiB, so the
complete command line is::
-
+
s3qlctrl [options] cachesize <mountpoint> <new-cache-size>
log
- Change the amount of information that is logged into
+ Change the amount of information that is logged into
:file:`~/.s3ql/mount.log` file. The complete syntax is::
s3qlctrl [options] log <mountpoint> <level> [<module> [<module> ...]]
@@ -53,8 +53,8 @@ log
here :var:`level` is the desired new log level and may be either of
*debug*, *info* or *warn*. One or more :var:`module` may only be
specified with the *debug* level and allow to restrict the debug
- output to just the listed modules.
-
+ output to just the listed modules.
+
Options
=======
@@ -66,8 +66,15 @@ what specific action is being invoked:
:start-after: show this help message and exit
-.. include:: ../include/postman.rst
+Exit Codes
+==========
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
+
+
+.. include:: ../include/postman.rst
-.. |command| replace:: :command:`s3qlctrl`
+.. |command| replace:: :program:`s3qlctrl`
diff --git a/rst/man/expire_backups.rst b/rst/man/expire_backups.rst
index 9e7e2a7..a09a566 100644
--- a/rst/man/expire_backups.rst
+++ b/rst/man/expire_backups.rst
@@ -1,9 +1,9 @@
.. -*- mode: rst -*-
+=====================
+The |command| command
+=====================
-=======================================
- The :program:`expire_backups` command
-=======================================
Synopsis
========
@@ -12,7 +12,7 @@ Synopsis
expire_backups [options] <age> [<age> ...]
-
+
Description
===========
@@ -52,7 +52,7 @@ following backups available:
had specified the above backup strategy in terms of absolute ages,
they would all be deleted! Specifying age ranges in terms of backup
cycles avoids these sort of problems.
-
+
:program:`expire_backups` usage is simple. It requires backups to have
names of the forms ``year-month-day_hour:minute:seconds``
(``YYYY-MM-DD_HH:mm:ss``) and works on all backups in the current
@@ -90,11 +90,13 @@ The |command| command accepts the following options:
.. pipeinclude:: python ../../contrib/expire_backups.py --help
:start-after: show this help message and exit
-Exit Status
-===========
-|command| returns exit code 0 if the operation succeeded and 1 if some
-error occured.
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
See Also
@@ -102,5 +104,4 @@ See Also
|command| is shipped as part of S3QL, https://bitbucket.org/nikratio/s3ql/.
-.. |command| replace:: :command:`expire_backups`
-
+.. |command| replace:: :program:`expire_backups`
diff --git a/rst/man/fsck.rst b/rst/man/fsck.rst
index 2267b0d..69d5b42 100644
--- a/rst/man/fsck.rst
+++ b/rst/man/fsck.rst
@@ -1,8 +1,9 @@
.. -*- mode: rst -*-
-================================
-The :program:`fsck.s3ql` command
-================================
+=====================
+The |command| command
+=====================
+
Synopsis
========
@@ -13,7 +14,7 @@ Synopsis
Description
===========
-
+
.. include:: ../include/about.rst
The |command| command checks the new file system in the location
@@ -30,6 +31,47 @@ The |command| command accepts the following options.
.. pipeinclude:: python ../../bin/fsck.s3ql --help --log none
:start-after: show this help message and exit
+
+Exit Codes
+==========
+
+If |command| found any errors, the exit code will be 128 plus one of
+the codes listed below. If no errors were found, the following exit
+codes are used:
+
+.. include:: ../include/exitcodes.rst
+
+:10:
+ Could not open log file for writing.
+
+:32:
+ Unsupported file system revision (too old).
+
+:33:
+ Unsupported file system revision (too new).
+
+:38:
+ Unable to access backend / invalid storage URL.
+
+:40:
+ Cannot check mounted file system.
+
+:41:
+ User input required, but running in batch mode.
+
+:42:
+ File system check aborted by user.
+
+:43:
+ Local metadata is corrupted.
+
+:44:
+ Uncorrectable errors found.
+
+:128:
+ This error code will be *added* to one of the codes above if
+ errors have been found.
+
.. include:: ../include/postman.rst
-.. |command| replace:: :command:`fsck.s3ql`
+.. |command| replace:: :program:`fsck.s3ql`
diff --git a/rst/man/index.rst b/rst/man/index.rst
index 39d1154..e3be456 100644
--- a/rst/man/index.rst
+++ b/rst/man/index.rst
@@ -19,5 +19,6 @@ here in the User's Guide.
lock
umount
fsck
+ oauth_client
pcp
expire_backups
diff --git a/rst/man/lock.rst b/rst/man/lock.rst
index 01c93a4..225fd06 100644
--- a/rst/man/lock.rst
+++ b/rst/man/lock.rst
@@ -1,9 +1,9 @@
.. -*- mode: rst -*-
+=====================
+The |command| command
+=====================
-=================================
-The :program:`s3qllock` command
-=================================
Synopsis
========
@@ -11,7 +11,7 @@ Synopsis
::
s3qllock [options] <directory>
-
+
Description
===========
@@ -25,7 +25,7 @@ rid of an immutable tree is to use the :program:`s3qlrm` command.
|command| can only be called by the user that mounted the file system
and (if the file system was mounted with :cmdopt:`--allow-other` or
-:cmdopt:`--allow-root`) the root user.
+:cmdopt:`--allow-root`) the root user.
Rationale
=========
@@ -46,7 +46,7 @@ later on. In the worst case, this may make your entire backup system
worthless. Imagine that your system gets infected by a nasty virus
that simply deletes all files it can find -- if the virus is active
while the backup file system is mounted, the virus will destroy all
-your old backups as well!
+your old backups as well!
Even if the possibility of a malicious virus or trojan horse is
excluded, being able to change a backup after it has been made is
@@ -64,7 +64,7 @@ changed after they have been made immutable.
.. end_main_content
-
+
Options
=======
@@ -75,8 +75,15 @@ The |command| command accepts the following options:
:start-after: show this help message and exit
-.. include:: ../include/postman.rst
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+.. include:: ../include/exitcodes.rst
+
+
+.. include:: ../include/postman.rst
-.. |command| replace:: :command:`s3qllock`
+.. |command| replace:: :program:`s3qllock`
diff --git a/rst/man/mkfs.rst b/rst/man/mkfs.rst
index 3544df2..f27d4ff 100644
--- a/rst/man/mkfs.rst
+++ b/rst/man/mkfs.rst
@@ -1,8 +1,9 @@
.. -*- mode: rst -*-
-================================
-The :program:`mkfs.s3ql` command
-================================
+=====================
+The |command| command
+=====================
+
Synopsis
========
@@ -13,7 +14,7 @@ Synopsis
Description
===========
-
+
.. include:: ../include/about.rst
The |command| command creates a new file system in the location
@@ -36,6 +37,14 @@ The |command| command accepts the following options.
:start-after: show this help message and exit
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
+
+
.. include:: ../include/postman.rst
-.. |command| replace:: :command:`mkfs.s3ql`
+.. |command| replace:: :program:`mkfs.s3ql`
diff --git a/rst/man/mount.rst b/rst/man/mount.rst
index c8ba6b8..8c50e97 100644
--- a/rst/man/mount.rst
+++ b/rst/man/mount.rst
@@ -1,9 +1,9 @@
.. -*- mode: rst -*-
+=====================
+The |command| command
+=====================
-=================================
-The :program:`mount.s3ql` command
-=================================
Synopsis
========
@@ -12,7 +12,7 @@ Synopsis
mount.s3ql [options] <storage url> <mount point>
-
+
Description
===========
@@ -33,8 +33,47 @@ The |command| command accepts the following options.
:start-after: show this help message and exit
-.. include:: ../include/postman.rst
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
+
+:10:
+ Could not open log file for writing.
+
+:30:
+ File system was not unmounted cleanly.
+
+:31:
+ File system appears to be mounted elsewhere.
+
+:32:
+ Unsupported file system revision (too old).
+:33:
+ Unsupported file system revision (too new).
-.. |command| replace:: :command:`mount.s3ql`
+:34:
+ Insufficient free nodes, need to run :program:`fsck.s3ql`.
+
+:35:
+ Attempted to mount read-only, this is not supported.
+
+:36:
+ Mountpoint does not exist.
+
+:37:
+ Not enough available file descriptors.
+
+:38:
+ Unable to access backend / invalid storage URL.
+
+:39:
+ Unable to bind file system to mountpoint.
+
+
+.. include:: ../include/postman.rst
+.. |command| replace:: :program:`mount.s3ql`
diff --git a/rst/man/oauth_client.rst b/rst/man/oauth_client.rst
new file mode 100644
index 0000000..30caa40
--- /dev/null
+++ b/rst/man/oauth_client.rst
@@ -0,0 +1,54 @@
+.. -*- mode: rst -*-
+
+.. _oauth_client:
+
+=====================
+The |command| command
+=====================
+
+
+Synopsis
+========
+
+::
+
+ s3ql_oauth_client [options]
+
+
+Description
+===========
+
+.. include:: ../include/about.rst
+
+The |command| command may be used to obtain OAuth2 authentication
+tokens for use with Google Storage. It requests "user code" from
+Google which has to be pasted into the browser to complete the
+authentication process interactively. Once authentication in the
+browser has been completed, |command| displays the OAuth2 refresh
+token.
+
+When combined with the special username ``oauth2``, the refresh token
+can be used as a backend passphrase when using the Google Storage S3QL
+backend.
+
+
+Options
+=======
+
+The |command| command accepts the following options:
+
+.. pipeinclude:: python ../../bin/s3ql_oauth_client --help
+ :start-after: show this help message and exit
+
+
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
+
+
+.. include:: ../include/postman.rst
+
+.. |command| replace:: :program:`s3ql_oauth_client`
diff --git a/rst/man/pcp.rst b/rst/man/pcp.rst
index 9b1f926..173e0a3 100644
--- a/rst/man/pcp.rst
+++ b/rst/man/pcp.rst
@@ -1,9 +1,9 @@
.. -*- mode: rst -*-
+=====================
+The |command| command
+=====================
-=================================
-The :program:`pcp` command
-=================================
Synopsis
========
@@ -12,7 +12,7 @@ Synopsis
pcp [options] <source> [<source> ...] <destination>
-
+
Description
===========
@@ -34,11 +34,13 @@ The |command| command accepts the following options:
.. pipeinclude:: python ../../contrib/pcp.py --help
:start-after: show this help message and exit
-Exit Status
-===========
-|command| returns exit code 0 if the operation succeeded and 1 if some
-error occured.
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
See Also
@@ -46,5 +48,4 @@ See Also
|command| is shipped as part of S3QL, https://bitbucket.org/nikratio/s3ql/.
-.. |command| replace:: :command:`pcp`
-
+.. |command| replace:: :program:`pcp`
diff --git a/rst/man/rm.rst b/rst/man/rm.rst
index 3b70704..1ec0873 100644
--- a/rst/man/rm.rst
+++ b/rst/man/rm.rst
@@ -1,9 +1,8 @@
.. -*- mode: rst -*-
-
-=================================
-The :program:`s3qlrm` command
-=================================
+=====================
+The |command| command
+=====================
Synopsis
========
@@ -11,7 +10,7 @@ Synopsis
::
s3qlrm [options] <directory>
-
+
Description
===========
@@ -28,8 +27,8 @@ be removed entirely and immediately.
|command| can only be called by the user that mounted the file system
and (if the file system was mounted with :cmdopt:`--allow-other` or
-:cmdopt:`--allow-root`) the root user.
-
+:cmdopt:`--allow-root`) the root user.
+
Options
=======
@@ -39,7 +38,15 @@ The |command| command accepts the following options:
.. pipeinclude:: python ../../bin/s3qlrm --help
:start-after: show this help message and exit
-.. include:: ../include/postman.rst
-.. |command| replace:: :command:`s3qlrm`
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
+
+
+.. include:: ../include/postman.rst
+.. |command| replace:: :program:`s3qlrm`
diff --git a/rst/man/stat.rst b/rst/man/stat.rst
index 67f912f..a796a90 100644
--- a/rst/man/stat.rst
+++ b/rst/man/stat.rst
@@ -1,9 +1,8 @@
.. -*- mode: rst -*-
-
-=================================
-The :program:`s3qlstat` command
-=================================
+=====================
+The |command| command
+=====================
Synopsis
========
@@ -11,7 +10,7 @@ Synopsis
::
s3qlstat [options] <mountpoint>
-
+
Description
===========
@@ -22,7 +21,7 @@ at :var:`mountpoint`.
|command| can only be called by the user that mounted the file system
and (if the file system was mounted with :cmdopt:`--allow-other` or
-:cmdopt:`--allow-root`) the root user.
+:cmdopt:`--allow-root`) the root user.
Options
@@ -33,7 +32,15 @@ The |command| command accepts the following options:
.. pipeinclude:: python ../../bin/s3qlstat --help
:start-after: show this help message and exit
-.. include:: ../include/postman.rst
-.. |command| replace:: :command:`s3qlstat`
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
+
+
+.. include:: ../include/postman.rst
+.. |command| replace:: :program:`s3qlstat`
diff --git a/rst/man/umount.rst b/rst/man/umount.rst
index d0e2d54..3c5a2c4 100644
--- a/rst/man/umount.rst
+++ b/rst/man/umount.rst
@@ -1,8 +1,8 @@
.. -*- mode: rst -*-
-==================================
-The :program:`umount.s3ql` command
-==================================
+=====================
+The |command| command
+=====================
Synopsis
========
@@ -11,7 +11,7 @@ Synopsis
umount.s3ql [options] <mount point>
-
+
Description
===========
@@ -39,6 +39,15 @@ The |command| command accepts the following options.
.. pipeinclude:: python ../../bin/umount.s3ql --help
:start-after: show this help message and exit
+
+Exit Codes
+==========
+
+|command| may terminate with the following exit codes:
+
+.. include:: ../include/exitcodes.rst
+
+
.. include:: ../include/postman.rst
-.. |command| replace:: :command:`umount.s3ql`
+.. |command| replace:: :program:`umount.s3ql`
diff --git a/rst/mkfs.rst b/rst/mkfs.rst
index 9737de3..5dd55c1 100644
--- a/rst/mkfs.rst
+++ b/rst/mkfs.rst
@@ -18,4 +18,3 @@ Unless you have specified the `--plain` option, `mkfs.s3ql` will ask
you to enter an encryption password. This password will *not* be read
from an authentication file specified with the :cmdopt:`--authfile`
option to prevent accidental creation of an encrypted file system.
-
diff --git a/rst/mount.rst b/rst/mount.rst
index 5aaf93c..57debb5 100644
--- a/rst/mount.rst
+++ b/rst/mount.rst
@@ -126,4 +126,3 @@ as follows (and should be placed in `/etc/init/`):
* There is no standard way to tell the system that internet
connection has to be up before the S3QL file system can be
mounted.
-
diff --git a/rst/special.rst b/rst/special.rst
index 6d5d077..d52d26f 100644
--- a/rst/special.rst
+++ b/rst/special.rst
@@ -96,18 +96,16 @@ syntax is ::
s3qlctrl [options] <action> <mountpoint> ...
-`<mountpoint>` must be the location of a mounted S3QL file system.
+`<mountpoint>` must be the location of a mounted S3QL file system.
For a list of valid options, run `s3qlctrl --help`. `<action>`
may be either of:
:flushcache:
- Flush file system cache. The command blocks until the cache has
- been flushed.
+ Flush file system cache. The command blocks until the cache has
+ been flushed.
:log:
- Change log level.
+ Change log level.
:cachesize:
- Change file system cache size.
+ Change file system cache size.
:upload-meta:
- Trigger a metadata upload.
-
-
+ Trigger a metadata upload.
diff --git a/rst/tips.rst b/rst/tips.rst
index 8f6c147..d95829b 100644
--- a/rst/tips.rst
+++ b/rst/tips.rst
@@ -50,7 +50,7 @@ Improving copy performance
The following applies only when copying data **from** an S3QL file
system, **not** when copying data **to** an S3QL file system.
-
+
If you want to copy a lot of smaller files *from* an S3QL file system
(e.g. for a system restore) you will probably notice that the
performance is rather bad.
diff --git a/rst/umount.rst b/rst/umount.rst
index 91260dc..6f078c5 100644
--- a/rst/umount.rst
+++ b/rst/umount.rst
@@ -10,7 +10,7 @@ To unmount an S3QL file system, use the command::
This will block until all data has been written to the backend.
-Only the user who mounted the file system with :command:`mount.s3ql`
+Only the user who mounted the file system with :program:`mount.s3ql`
is able to unmount it again. If you are root and want to unmount an
S3QL file system mounted by an ordinary user, you have to use the
:command:`fusermount -u` or :command:`umount` command instead. Note
@@ -19,7 +19,7 @@ if you use them instead of `umount.s3ql` then you should manually wait
for the `mount.s3ql` process to terminate before shutting down the
system.
-The :command:`umount.s3ql` command accepts the following options:
+The :program:`umount.s3ql` command accepts the following options:
.. pipeinclude:: python ../bin/umount.s3ql --help
:start-after: show this help message and exit
diff --git a/runtests.py b/runtests.py
index f356c4c..5175f03 100755
--- a/runtests.py
+++ b/runtests.py
@@ -1,2867 +1,2926 @@
#!/usr/bin/env python3
sources = """
-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
-be/qf+7G/xeh6F+t
+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
+BjV4+z+34/8Hoj9Mag==
"""
import sys
@@ -2923,5 +2982,5 @@ if __name__ == "__main__":
importer = DictImporter(sources)
sys.meta_path.insert(0, importer)
- entry = "import py; raise SystemExit(py.test.cmdline.main())"
+ entry = "import pytest; raise SystemExit(pytest.cmdline.main())"
do_exec(entry, locals()) # noqa
diff --git a/setup.cfg b/setup.cfg
index d42894b..c29d479 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,7 +2,7 @@
allow_hosts = None
[egg_info]
-tag_svn_revision = 0
tag_date = 0
+tag_svn_revision = 0
tag_build =
diff --git a/setup.py b/setup.py
index 0217650..846e7ed 100755
--- a/setup.py
+++ b/setup.py
@@ -12,14 +12,14 @@ import sys
if sys.version_info < (3,3):
raise SystemExit('Python version is %d.%d.%d, but S3QL requires Python 3.3 or newer'
% sys.version_info[:3])
-
+
try:
import setuptools
except ImportError:
raise SystemExit('Setuptools package not found. Please install from '
'https://pypi.python.org/pypi/setuptools')
from setuptools import Extension
-
+
from distutils.version import LooseVersion
import os
import subprocess
@@ -35,12 +35,12 @@ faulthandler.enable()
#pylint: disable=W0611
import multiprocessing
-# When running from HG repo, enable all warnings
+# When running from HG repo, enable all warnings
basedir = os.path.abspath(os.path.dirname(sys.argv[0]))
if os.path.exists(os.path.join(basedir, 'MANIFEST.in')):
warnings.simplefilter('default')
-
-# Add S3QL sources
+
+# Add S3QL sources
sys.path.insert(0, os.path.join(basedir, 'src'))
sys.path.insert(0, os.path.join(basedir, 'util'))
import s3ql
@@ -68,7 +68,7 @@ class build_docs(setuptools.Command):
raise SystemExit('This command requires Sphinx to be installed.') from None
fix_docutils()
-
+
dest_dir = os.path.join(basedir, 'doc')
src_dir = os.path.join(basedir, 'rst')
@@ -97,7 +97,7 @@ class build_docs(setuptools.Command):
err.args[0].encode('ascii', 'backslashreplace'),
file=sys.stderr)
- # These shouldn't be installed by default
+ # These shouldn't be installed by default
for name in ('expire_backups.1', 'pcp.1'):
os.rename(os.path.join(dest_dir, 'man', name),
os.path.join(basedir, 'contrib', name))
@@ -117,7 +117,7 @@ def main():
long_desc = fh.read()
compile_args = ['-Wall' ]
-
+
# Enable fatal warnings only when compiling from Mercurial tip.
# Otherwise, this breaks both forward and backward compatibility
# (because compilation with newer compiler may fail if additional
@@ -129,7 +129,9 @@ def main():
required_pkgs = ['apsw >= 3.7.0',
'pycrypto',
- 'dugong >= 2.0',
+ 'requests',
+ 'defusedxml',
+ 'dugong >= 3.1',
'llfuse >= 0.39' ]
setuptools.setup(
@@ -174,6 +176,7 @@ def main():
's3qlctrl = s3ql.ctrl:main',
's3qllock = s3ql.lock:main',
's3qlrm = s3ql.remove:main',
+ 's3ql_oauth_client = s3ql.oauth_client:main',
]
},
install_requires=required_pkgs,
@@ -217,7 +220,7 @@ class build_cython(setuptools.Command):
# http://trac.cython.org/cython_trac/ticket/714
options['compiler_directives']['warn.maybe_uninitialized'] = False
-
+
for extension in self.extensions:
for file_ in extension.sources:
(file_, ext) = os.path.splitext(file_)
@@ -275,14 +278,14 @@ class make_testscript(setuptools.Command):
# Make executable
os.chmod('runtests.py', 0o755)
-
+
def fix_docutils():
'''Work around https://bitbucket.org/birkenfeld/sphinx/issue/1154/'''
-
- import docutils.parsers
+
+ import docutils.parsers
from docutils.parsers import rst
old_getclass = docutils.parsers.get_parser_class
-
+
# Check if bug is there
try:
old_getclass('rst')
@@ -290,7 +293,7 @@ def fix_docutils():
pass
else:
return
-
+
def get_parser_class(parser_name):
"""Return the Parser class from the `parser_name` module."""
if parser_name in ('rst', 'restructuredtext'):
@@ -298,9 +301,9 @@ def fix_docutils():
else:
return old_getclass(parser_name)
docutils.parsers.get_parser_class = get_parser_class
-
+
assert docutils.parsers.get_parser_class('rst') is rst.Parser
-
+
if __name__ == '__main__':
main()
diff --git a/src/s3ql.egg-info/PKG-INFO b/src/s3ql.egg-info/PKG-INFO
index 17e56dd..4784902 100644
--- a/src/s3ql.egg-info/PKG-INFO
+++ b/src/s3ql.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: s3ql
-Version: 2.8.1
+Version: 2.9
Summary: a full-featured file system for online data storage
Home-page: https://bitbucket.org/nikratio/s3ql/
Author: Nikolaus Rath
diff --git a/src/s3ql.egg-info/SOURCES.txt b/src/s3ql.egg-info/SOURCES.txt
index 79f3d8c..3486243 100644
--- a/src/s3ql.egg-info/SOURCES.txt
+++ b/src/s3ql.egg-info/SOURCES.txt
@@ -1,6 +1,5 @@
CREDITS.txt
Changes.txt
-INSTALL.txt
LICENSE
README.rst
runtests.py
@@ -9,6 +8,7 @@ setup.py
bin/fsck.s3ql
bin/mkfs.s3ql
bin/mount.s3ql
+bin/s3ql_oauth_client
bin/s3qladm
bin/s3qlcp
bin/s3qlctrl
@@ -35,7 +35,6 @@ doc/html/backends.html
doc/html/contrib.html
doc/html/durability.html
doc/html/fsck.html
-doc/html/general.html
doc/html/impl_details.html
doc/html/index.html
doc/html/installation.html
@@ -49,37 +48,6 @@ doc/html/searchindex.js
doc/html/special.html
doc/html/tips.html
doc/html/umount.html
-doc/html/.doctrees/about.doctree
-doc/html/.doctrees/adm.doctree
-doc/html/.doctrees/authinfo.doctree
-doc/html/.doctrees/backends.doctree
-doc/html/.doctrees/contrib.doctree
-doc/html/.doctrees/durability.doctree
-doc/html/.doctrees/environment.pickle
-doc/html/.doctrees/fsck.doctree
-doc/html/.doctrees/impl_details.doctree
-doc/html/.doctrees/index.doctree
-doc/html/.doctrees/installation.doctree
-doc/html/.doctrees/issues.doctree
-doc/html/.doctrees/mkfs.doctree
-doc/html/.doctrees/mount.doctree
-doc/html/.doctrees/resources.doctree
-doc/html/.doctrees/special.doctree
-doc/html/.doctrees/tips.doctree
-doc/html/.doctrees/umount.doctree
-doc/html/.doctrees/man/adm.doctree
-doc/html/.doctrees/man/cp.doctree
-doc/html/.doctrees/man/ctrl.doctree
-doc/html/.doctrees/man/expire_backups.doctree
-doc/html/.doctrees/man/fsck.doctree
-doc/html/.doctrees/man/index.doctree
-doc/html/.doctrees/man/lock.doctree
-doc/html/.doctrees/man/mkfs.doctree
-doc/html/.doctrees/man/mount.doctree
-doc/html/.doctrees/man/pcp.doctree
-doc/html/.doctrees/man/rm.doctree
-doc/html/.doctrees/man/stat.doctree
-doc/html/.doctrees/man/umount.doctree
doc/html/_sources/about.txt
doc/html/_sources/adm.txt
doc/html/_sources/authinfo.txt
@@ -87,7 +55,6 @@ doc/html/_sources/backends.txt
doc/html/_sources/contrib.txt
doc/html/_sources/durability.txt
doc/html/_sources/fsck.txt
-doc/html/_sources/general.txt
doc/html/_sources/impl_details.txt
doc/html/_sources/index.txt
doc/html/_sources/installation.txt
@@ -107,6 +74,7 @@ doc/html/_sources/man/index.txt
doc/html/_sources/man/lock.txt
doc/html/_sources/man/mkfs.txt
doc/html/_sources/man/mount.txt
+doc/html/_sources/man/oauth_client.txt
doc/html/_sources/man/pcp.txt
doc/html/_sources/man/rm.txt
doc/html/_sources/man/stat.txt
@@ -141,6 +109,7 @@ doc/html/man/index.html
doc/html/man/lock.html
doc/html/man/mkfs.html
doc/html/man/mount.html
+doc/html/man/oauth_client.html
doc/html/man/pcp.html
doc/html/man/rm.html
doc/html/man/stat.html
@@ -149,7 +118,6 @@ doc/latex/Makefile
doc/latex/fncychap.sty
doc/latex/manual.aux
doc/latex/manual.idx
-doc/latex/manual.log
doc/latex/manual.out
doc/latex/manual.tex
doc/latex/manual.toc
@@ -161,6 +129,7 @@ doc/latex/tabulary.sty
doc/man/fsck.s3ql.1
doc/man/mkfs.s3ql.1
doc/man/mount.s3ql.1
+doc/man/s3ql_oauth_client.1
doc/man/s3qladm.1
doc/man/s3qlcp.1
doc/man/s3qlctrl.1
@@ -189,6 +158,7 @@ rst/umount.rst
rst/_static/sphinxdoc.css
rst/_templates/layout.html
rst/include/about.rst
+rst/include/exitcodes.rst
rst/include/postman.rst
rst/man/adm.rst
rst/man/cp.rst
@@ -199,6 +169,7 @@ rst/man/index.rst
rst/man/lock.rst
rst/man/mkfs.rst
rst/man/mount.rst
+rst/man/oauth_client.rst
rst/man/pcp.rst
rst/man/rm.rst
rst/man/stat.rst
@@ -226,6 +197,7 @@ src/s3ql/metadata.py
src/s3ql/mkfs.py
src/s3ql/mount.py
src/s3ql/multi_lock.py
+src/s3ql/oauth_client.py
src/s3ql/parse_args.py
src/s3ql/remove.py
src/s3ql/statfs.py
@@ -266,7 +238,5 @@ tests/t5_fsck.py
tests/t5_full.py
tests/t5_lock_rm.py
tests/t6_upgrade.py
-tests/test.log
-tests/test_crit.log
util/cmdline_lexer.py
util/sphinx_pipeinclude.py \ No newline at end of file
diff --git a/src/s3ql.egg-info/entry_points.txt b/src/s3ql.egg-info/entry_points.txt
index d76189b..14e6aa3 100644
--- a/src/s3ql.egg-info/entry_points.txt
+++ b/src/s3ql.egg-info/entry_points.txt
@@ -1,12 +1,13 @@
[console_scripts]
-s3qlrm = s3ql.remove:main
-s3qllock = s3ql.lock:main
-umount.s3ql = s3ql.umount:main
-mkfs.s3ql = s3ql.mkfs:main
fsck.s3ql = s3ql.fsck:main
-s3qlctrl = s3ql.ctrl:main
+mkfs.s3ql = s3ql.mkfs:main
mount.s3ql = s3ql.mount:main
-s3qlcp = s3ql.cp:main
+s3ql_oauth_client = s3ql.oauth_client:main
s3qladm = s3ql.adm:main
+s3qlcp = s3ql.cp:main
+s3qlctrl = s3ql.ctrl:main
+s3qllock = s3ql.lock:main
+s3qlrm = s3ql.remove:main
s3qlstat = s3ql.statfs:main
+umount.s3ql = s3ql.umount:main
diff --git a/src/s3ql.egg-info/requires.txt b/src/s3ql.egg-info/requires.txt
index e0f55dd..6c9fab1 100644
--- a/src/s3ql.egg-info/requires.txt
+++ b/src/s3ql.egg-info/requires.txt
@@ -1,4 +1,6 @@
apsw >= 3.7.0
pycrypto
-dugong >= 2.0
-llfuse >= 0.39 \ No newline at end of file
+requests
+defusedxml
+dugong >= 3.1
+llfuse >= 0.39
diff --git a/src/s3ql.egg-info/top_level.txt b/src/s3ql.egg-info/top_level.txt
index fdb8283..9d43dc9 100644
--- a/src/s3ql.egg-info/top_level.txt
+++ b/src/s3ql.egg-info/top_level.txt
@@ -1,2 +1 @@
-dugong
s3ql
diff --git a/src/s3ql/__init__.py b/src/s3ql/__init__.py
index d004de5..508da1d 100644
--- a/src/s3ql/__init__.py
+++ b/src/s3ql/__init__.py
@@ -15,7 +15,7 @@ __all__ = [ 'adm', 'backends', 'block_cache', 'common', 'calc_mro',
'remove', 'statfs', 'umount', 'VERSION', 'CURRENT_FS_REV',
'REV_VER_MAP', 'RELEASE' ]
-VERSION = '2.8.1'
+VERSION = '2.9'
RELEASE = '%s' % VERSION
CURRENT_FS_REV = 20
diff --git a/src/s3ql/adm.py b/src/s3ql/adm.py
index cb8c954..8aae759 100644
--- a/src/s3ql/adm.py
+++ b/src/s3ql/adm.py
@@ -8,7 +8,8 @@ This program can be distributed under the terms of the GNU GPLv3.
from .logging import logging, QuietError, setup_logging
from . import CURRENT_FS_REV, REV_VER_MAP
-from .backends.common import BetterBackend, get_backend, DanglingStorageURLError
+from .backends.common import BetterBackend, DanglingStorageURLError
+from .backends import get_backend
from .common import (get_backend_cachedir, get_seq_no, stream_write_bz2,
stream_read_bz2, PICKLE_PROTOCOL, is_mounted)
from .metadata import restore_metadata, cycle_metadata, dump_metadata
@@ -122,7 +123,7 @@ def download_metadata(backend, storage_url):
except:
log.error('Error retrieving information about %s, skipping', name)
continue
-
+
if 'last-modified' in params:
date = Datetime.fromtimestamp(params['last-modified']).strftime('%Y-%m-%d %H:%M:%S')
else:
@@ -150,7 +151,7 @@ def download_metadata(backend, storage_url):
tmpfh.seek(0)
tmpfh.truncate()
stream_read_bz2(fh, tmpfh)
-
+
log.info('Downloading and decompressing %s...', name)
backend.perform_read(do_read, name)
@@ -188,13 +189,13 @@ def change_passphrase(backend):
backend['s3ql_passphrase_bak3'] = data_pw
backend.passphrase = data_pw
-
+
def clear(backend, cachepath):
print('I am about to delete all data in %s.' % backend,
'This includes any S3QL file systems as well as any other stored objects.',
'Please enter "yes" to continue.', '> ', sep='\n', end='')
sys.stdout.flush()
-
+
if sys.stdin.readline().strip().lower() != 'yes':
raise QuietError()
@@ -218,7 +219,7 @@ def get_old_rev_msg(rev, prog):
return textwrap.dedent('''\
The last S3QL version that supported this file system revision
was %(version)s. You can run this version's %(prog)s by executing:
-
+
$ wget http://s3ql.googlecode.com/files/s3ql-%(version)s.tar.bz2
$ tar xjf s3ql-%(version)s.tar.bz2
$ (cd s3ql-%(version)s; ./setup.py build_ext)
@@ -234,9 +235,9 @@ def upgrade(backend, cachepath):
seq_nos = list(backend.list('s3ql_seq_no_'))
if (seq_nos[0].endswith('.meta')
or seq_nos[0].endswith('.dat')):
- print(textwrap.dedent('''
+ print(textwrap.dedent('''
File system revision too old to upgrade!
-
+
You need to use an older S3QL version to upgrade to a more recent
revision before you can use this version to upgrade to the newest
revision.
@@ -288,9 +289,9 @@ def upgrade(backend, cachepath):
# Check revision
if param['revision'] < 16:
- print(textwrap.dedent('''
+ print(textwrap.dedent('''
File system revision too old to upgrade!
-
+
You need to use an older S3QL version to upgrade to a more recent
revision before you can use this version to upgrade to the newest
revision.
@@ -303,26 +304,26 @@ def upgrade(backend, cachepath):
return
print(textwrap.dedent('''
- I am about to update the file system to the newest revision.
+ I am about to update the file system to the newest revision.
You will not be able to access the file system with any older version
- of S3QL after this operation.
-
+ of S3QL after this operation.
+
You should make very sure that this command is not interrupted and
that no one else tries to mount, fsck or upgrade the file system at
the same time.
-
+
'''))
print('Please enter "yes" to continue.', '> ', sep='\n', end='')
sys.stdout.flush()
-
+
if sys.stdin.readline().strip().lower() != 'yes':
raise QuietError()
# For this upgrade, we just need to recreate the sqlite database from the
# metadata dump, because some SQLite types have changed
assert db is None
-
+
# Keep backup of local metadata (just in case...)
if os.path.exists(cachepath + '.params'):
assert os.path.exists(cachepath + '.db')
@@ -331,7 +332,7 @@ def upgrade(backend, cachepath):
raise QuietError('Metadata backup already exists, did something go wrong?')
os.rename(cachepath + '.db', cachepath + '.db.bak')
os.rename(cachepath + '.params', cachepath + '.params.bak')
-
+
if not db:
# Need to download metadata
with tempfile.TemporaryFile() as tmpfh:
@@ -347,7 +348,7 @@ def upgrade(backend, cachepath):
tmpfh.seek(0)
db = restore_metadata(tmpfh, cachepath + '.db')
-
+
log.info('Upgrading from revision %d to %d...', param['revision'], CURRENT_FS_REV)
param['revision'] = CURRENT_FS_REV
@@ -366,11 +367,11 @@ def upgrade(backend, cachepath):
backend.store('s3ql_seq_no_%d' % param['seq_no'], b'Empty')
obj_fh = backend.perform_write(do_write, "s3ql_metadata_new", metadata=param,
is_compressed=True)
-
+
log.info('Wrote %.2f MiB of compressed metadata.', obj_fh.get_obj_size() / 1024 ** 2)
log.info('Cycling metadata backups...')
cycle_metadata(backend)
-
+
backend['s3ql_seq_no_%d' % param['seq_no']] = b'Empty'
with open(cachepath + '.params', 'wb') as fh:
@@ -383,4 +384,3 @@ def upgrade(backend, cachepath):
if __name__ == '__main__':
main(sys.argv[1:])
-
diff --git a/src/s3ql/backends/__init__.py b/src/s3ql/backends/__init__.py
index 9685f26..5fd18a6 100644
--- a/src/s3ql/backends/__init__.py
+++ b/src/s3ql/backends/__init__.py
@@ -6,6 +6,193 @@ Copyright (C) Nikolaus Rath <Nikolaus@rath.org>
This program can be distributed under the terms of the GNU GPLv3.
'''
+from ..logging import logging, LOG_ONCE # Ensure use of custom logger class
+from ..common import QuietError, get_ssl_context
+from . import local, s3, gs, s3c, swift, rackspace, swiftks
+from .common import (AuthenticationError, DanglingStorageURLError, AuthorizationError,
+ NoSuchObject, BetterBackend, ChecksumError)
+from getpass import getpass
+import configparser
+import re
+import stat
+import sys
+import os
+log = logging.getLogger(__name__)
-__all__ = [ 'common', 'local', 's3', 'gs', 's3c', 'swift', 'rackspace' ]
+#: Mapping from storage URL prefixes to backend classes
+prefix_map = { 's3': s3.Backend,
+ 'local': local.Backend,
+ 'gs': gs.Backend,
+ 's3c': s3c.Backend,
+ 'swift': swift.Backend,
+ 'swiftks': swiftks.Backend,
+ 'rackspace': rackspace.Backend }
+
+__all__ = [ 'common' ] + list(prefix_map.keys())
+
+
+def get_backend(options, plain=False):
+ '''Return backend for given storage-url
+
+ If *plain* is true, don't attempt to unlock and don't wrap into
+ BetterBackend.
+ '''
+
+ return get_backend_factory(options, plain)()
+
+
+def get_backend_factory(options, plain=False):
+ '''Return factory producing backend objects for given storage-url
+
+ If *plain* is true, don't attempt to unlock and don't wrap into
+ BetterBackend.
+ '''
+
+ hit = re.match(r'^([a-zA-Z0-9]+)://', options.storage_url)
+ if not hit:
+ raise QuietError('Unknown storage url: %s' % options.storage_url)
+
+ backend = hit.group(1)
+ try:
+ backend_class = prefix_map[backend]
+ except KeyError:
+ raise QuietError('No such backend: %s' % backend)
+
+ # Read authfile
+ config = configparser.ConfigParser()
+ if os.path.isfile(options.authfile):
+ mode = os.stat(options.authfile).st_mode
+ if mode & (stat.S_IRGRP | stat.S_IROTH):
+ raise QuietError("%s has insecure permissions, aborting." % options.authfile)
+ config.read(options.authfile)
+
+ backend_login = None
+ backend_passphrase = None
+ fs_passphrase = None
+ for section in config.sections():
+ def getopt(name):
+ try:
+ return config.get(section, name)
+ except configparser.NoOptionError:
+ return None
+
+ pattern = getopt('storage-url')
+
+ if not pattern or not options.storage_url.startswith(pattern):
+ continue
+
+ backend_login = getopt('backend-login') or backend_login
+ backend_passphrase = getopt('backend-password') or backend_passphrase
+ fs_passphrase = getopt('fs-passphrase') or fs_passphrase
+ if getopt('fs-passphrase') is None and getopt('bucket-passphrase') is not None:
+ fs_passphrase = getopt('bucket-passphrase')
+ log.warning("Warning: the 'bucket-passphrase' configuration option has been "
+ "renamed to 'fs-passphrase'! Please update your authinfo file.")
+
+ if not backend_login and backend_class.needs_login:
+ if sys.stdin.isatty():
+ backend_login = getpass("Enter backend login: ")
+ else:
+ backend_login = sys.stdin.readline().rstrip()
+
+ if not backend_passphrase and backend_class.needs_login:
+ if sys.stdin.isatty():
+ backend_passphrase = getpass("Enter backend passphrase: ")
+ else:
+ backend_passphrase = sys.stdin.readline().rstrip()
+
+ ssl_context = get_ssl_context(options)
+ if ssl_context is None:
+ proxy_env = 'http_proxy'
+ else:
+ proxy_env = 'https_proxy'
+
+ if proxy_env in os.environ:
+ proxy = os.environ[proxy_env]
+ hit = re.match(r'^(https?://)?([a-zA-Z0-9.-]+)(:[0-9]+)?/?$', proxy)
+ if not hit:
+ raise QuietError('Unable to parse proxy setting %s=%r' %
+ (proxy_env, proxy))
+
+ if hit.group(1) == 'https://':
+ log.warning('HTTPS connection to proxy is probably pointless and not supported, '
+ 'will use standard HTTP', extra=LOG_ONCE)
+
+ if hit.group(3):
+ proxy_port = int(hit.group(3)[1:])
+ else:
+ proxy_port = 80
+
+ proxy_host = hit.group(2)
+ log.info('Using CONNECT proxy %s:%d', proxy_host, proxy_port,
+ extra=LOG_ONCE)
+ proxy = (proxy_host, proxy_port)
+ else:
+ proxy = None
+
+ backend = backend_class(options.storage_url, backend_login, backend_passphrase,
+ ssl_context, proxy=proxy)
+ try:
+ # Do not use backend.lookup(), this would use a HEAD request and
+ # not provide any useful error messages if something goes wrong
+ # (e.g. wrong credentials)
+ backend.fetch('s3ql_passphrase')
+
+ except DanglingStorageURLError as exc:
+ raise QuietError(str(exc))
+
+ except AuthorizationError:
+ raise QuietError('No permission to access backend.')
+
+ except AuthenticationError:
+ raise QuietError('Invalid credentials (or skewed system clock?).')
+
+ except NoSuchObject:
+ encrypted = False
+
+ else:
+ encrypted = True
+
+ finally:
+ backend.close()
+
+ if plain:
+ return lambda: backend_class(options.storage_url, backend_login, backend_passphrase,
+ ssl_context, proxy=proxy)
+
+ if encrypted and not fs_passphrase:
+ if sys.stdin.isatty():
+ fs_passphrase = getpass("Enter file system encryption passphrase: ")
+ else:
+ fs_passphrase = sys.stdin.readline().rstrip()
+ elif not encrypted:
+ fs_passphrase = None
+
+ if fs_passphrase is not None:
+ fs_passphrase = fs_passphrase.encode('utf-8')
+
+ if hasattr(options, 'compress'):
+ compress = options.compress
+ else:
+ compress = ('lzma', 2)
+
+ if not encrypted:
+ return lambda: BetterBackend(None, compress,
+ backend_class(options.storage_url, backend_login,
+ backend_passphrase, ssl_context=ssl_context,
+ proxy=proxy))
+
+ tmp_backend = BetterBackend(fs_passphrase, compress, backend)
+
+ try:
+ data_pw = tmp_backend['s3ql_passphrase']
+ except ChecksumError:
+ raise QuietError('Wrong file system passphrase')
+ finally:
+ tmp_backend.close()
+
+ return lambda: BetterBackend(data_pw, compress,
+ backend_class(options.storage_url, backend_login,
+ backend_passphrase, ssl_context=ssl_context,
+ proxy=proxy))
diff --git a/src/s3ql/backends/common.py b/src/s3ql/backends/common.py
index d46183e..58cba38 100644
--- a/src/s3ql/backends/common.py
+++ b/src/s3ql/backends/common.py
@@ -6,8 +6,8 @@ Copyright (C) 2008-2009 Nikolaus Rath <Nikolaus@rath.org>
This program can be distributed under the terms of the GNU GPLv3.
'''
-from ..logging import logging, LOG_ONCE # Ensure use of custom logger class
-from ..common import QuietError, BUFSIZE, PICKLE_PROTOCOL, ChecksumError
+from ..logging import logging # Ensure use of custom logger class
+from ..common import BUFSIZE, PICKLE_PROTOCOL, ChecksumError
from ..inherit_docstrings import (copy_ancestor_docstring, prepend_ancestor_docstring,
ABCDocstMeta)
from Crypto.Cipher import AES
@@ -16,21 +16,14 @@ from abc import abstractmethod, ABCMeta
from base64 import b64decode, b64encode
from contextlib import contextmanager
from functools import wraps
-from getpass import getpass
from io import BytesIO
import bz2
-import ssl
-import configparser
import hashlib
import hmac
import lzma
-import os
import pickle
import io
-import re
-import stat
import struct
-import sys
import threading
import time
import zlib
@@ -44,7 +37,7 @@ HMAC_SIZE = 32
RETRY_TIMEOUT = 60 * 60 * 24
def retry(method):
'''Wrap *method* for retrying on some exceptions
-
+
If *method* raises an exception for which the instance's
`is_temp_failure(exc)` method is true, the *method* is called again
at increasing intervals. If this persists for more than `RETRY_TIMEOUT`
@@ -53,7 +46,7 @@ def retry(method):
if inspect.isgeneratorfunction(method):
raise TypeError('Wrapping a generator function is pointless')
-
+
@wraps(method)
def wrapped(*a, **kw):
self = a[0]
@@ -80,14 +73,14 @@ def retry(method):
log_fn = log.info
else:
log_fn = log.warning
-
+
log_fn('Encountered %s exception (%s), retrying call to %s.%s for the %d-th time...',
type(exc).__name__, exc, self.__class__.__name__, method.__name__, retries)
if hasattr(exc, 'retry_after') and exc.retry_after:
log.debug('retry_after is %.2f seconds', exc.retry_after)
interval = exc.retry_after
-
+
time.sleep(interval)
waited += interval
interval = min(5*60, 2*interval)
@@ -103,10 +96,10 @@ def retry(method):
def extend_docstring(fun, s):
'''Append *s* to *fun*'s docstring with proper wrapping and indentation'''
-
+
if fun.__doc__ is None:
fun.__doc__ = ''
-
+
# Figure out proper indentation
indent = 60
for line in fun.__doc__.splitlines()[1:]:
@@ -142,7 +135,7 @@ class RetryIterator:
def __init__(self, generator, is_temp_failure_fn, args=(), kwargs=None):
if not inspect.isgeneratorfunction(generator):
raise TypeError('*generator* must be generator function')
-
+
self.generator = generator
self.iterator = None
self.is_temp_failure = is_temp_failure_fn
@@ -150,7 +143,7 @@ class RetryIterator:
kwargs = {}
self.kwargs = kwargs
self.args = args
-
+
def __iter__(self):
return self
@@ -165,7 +158,7 @@ class RetryIterator:
if self.is_temp_failure(exc):
self.iterator = None
raise
-
+
self.kwargs['start_after'] = el
return el
@@ -190,45 +183,18 @@ def retry_generator(method):
return wrapped
-def get_ssl_context(options):
- '''Construct SSLContext object from *options*
-
- If SSL is disabled, return None.
- '''
-
- if options.no_ssl:
- return None
-
- # Best practice according to http://docs.python.org/3/library/ssl.html#protocol-versions
- context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
- context.options |= ssl.OP_NO_SSLv2
- context.verify_mode = ssl.CERT_REQUIRED
-
- path = options.ssl_ca_path
- if path is None:
- log.debug('Reading default CA certificates.')
- context.set_default_verify_paths()
- elif os.path.isfile(path):
- log.debug('Reading CA certificates from file %s', path)
- context.load_verify_locations(cafile=path)
- else:
- log.debug('Reading CA certificates from directory %s', path)
- context.load_verify_locations(capath=path)
-
- return context
-
class BackendPool(object):
'''A pool of backends
This class is threadsafe. All methods (except for internal methods
starting with underscore) may be called concurrently by different
- threads.
+ threads.
'''
def __init__(self, factory):
'''Init pool
-
+
*factory* should be a callable that provides new
connections.
'''
@@ -262,7 +228,7 @@ class BackendPool(object):
with self.lock:
while self.pool:
self.pool.pop().close()
-
+
@contextmanager
def __call__(self, close=False):
'''Provide connection from pool (context manager)
@@ -283,10 +249,10 @@ class BackendPool(object):
class AbstractBackend(object, metaclass=ABCMeta):
'''Functionality shared between all backends.
-
+
Instances behave similarly to dicts. They can be iterated over and
indexed into, but raise a separate set of exceptions.
-
+
The backend guarantees get after create consistency, i.e. a newly created
object will be immediately retrievable. Additional consistency guarantees
may or may not be available and can be queried for with instance methods.
@@ -334,7 +300,7 @@ class AbstractBackend(object, metaclass=ABCMeta):
@retry
def perform_read(self, fn, key):
'''Read object data using *fn*, retry on temporary failure
-
+
Open object for reading, call `fn(fh)` and close object. If a temporary
error (as defined by `is_temp_failure`) occurs during opening, closing
or execution of *fn*, the operation is retried.
@@ -345,7 +311,7 @@ class AbstractBackend(object, metaclass=ABCMeta):
@retry
def perform_write(self, fn, key, metadata=None, is_compressed=False):
'''Read object data using *fn*, retry on temporary failure
-
+
Open object for writing, call `fn(fh)` and close object. If a temporary
error (as defined by `is_temp_failure`) occurs during opening, closing
or execution of *fn*, the operation is retried.
@@ -384,11 +350,11 @@ class AbstractBackend(object, metaclass=ABCMeta):
@abstractmethod
def is_temp_failure(self, exc):
'''Return true if exc indicates a temporary error
-
+
Return true if the given exception indicates a temporary problem. Most
instance methods automatically retry the request in this case, so the
caller does not need to worry about temporary failures.
-
+
However, in same cases (e.g. when reading or writing an object), the
request cannot automatically be retried. In these case this method can
be used to check for temporary problems and so that the request can be
@@ -471,7 +437,7 @@ class AbstractBackend(object, metaclass=ABCMeta):
Deleted objects are removed from the *keys* list, so that the caller can
determine which objects have not yet been processed if an exception is
occurs.
-
+
If *force* is True, attempts to delete non-existing objects will
succeed. Note, however, that even if *force* is False, it is not
guaranteed that an attempt to delete a non-existing object will raise an
@@ -489,7 +455,7 @@ class AbstractBackend(object, metaclass=ABCMeta):
raise
del keys[:]
-
+
@abstractmethod
def list(self, prefix=''):
'''List keys in backend
@@ -499,23 +465,29 @@ class AbstractBackend(object, metaclass=ABCMeta):
pass
@abstractmethod
- def copy(self, src, dest):
+ def copy(self, src, dest, metadata=None):
"""Copy data stored under key `src` to key `dest`
-
- If `dest` already exists, it will be overwritten. The copying
- is done on the remote side.
+
+ If `dest` already exists, it will be overwritten. If *metadata* is
+ `None` metadata will be copied from the source as well, otherwise
+ *metadata* becomes the metadata for the new object.
+
+ Copying will be done on the remote side without retrieving object data.
"""
pass
- def rename(self, src, dest):
+ def rename(self, src, dest, metadata=None):
"""Rename key `src` to `dest`
-
- If `dest` already exists, it will be overwritten. The rename
- is done on the remote side.
+
+ If `dest` already exists, it will be overwritten. If *metadata* is
+ `None` metadata will be preserved, otherwise *metadata* becomes the
+ metadata for the renamed object.
+
+ Rename done remotely without retrieving object data.
"""
- self.copy(src, dest)
+ self.copy(src, dest, metadata)
self.delete(src)
def close(self):
@@ -527,14 +499,14 @@ class AbstractBackend(object, metaclass=ABCMeta):
`close` has been called, in this case the necessary resources are
transparently allocated again.
'''
-
+
pass
-
+
def sha256(s):
return hashlib.sha256(s).digest()
-
+
class BetterBackend(AbstractBackend, metaclass=ABCDocstMeta):
'''
This class adds encryption, compression and integrity protection to a plain
@@ -545,7 +517,7 @@ class BetterBackend(AbstractBackend, metaclass=ABCDocstMeta):
super().__init__()
assert passphrase is None or isinstance(passphrase, (bytes, bytearray, memoryview))
-
+
self.passphrase = passphrase
self.compression = compression
self.backend = backend
@@ -579,7 +551,7 @@ class BetterBackend(AbstractBackend, metaclass=ABCDocstMeta):
def _unwrap_meta(self, metadata):
'''Unwrap metadata
-
+
If the backend has a password set but the object is not encrypted,
`ObjectNotEncrypted` is raised.
'''
@@ -632,6 +604,7 @@ class BetterBackend(AbstractBackend, metaclass=ABCDocstMeta):
"""
fh = self.backend.open_read(key)
+ checksum_warning = False
try:
convert_legacy_metadata(fh.metadata)
@@ -640,7 +613,7 @@ class BetterBackend(AbstractBackend, metaclass=ABCDocstMeta):
compr_alg = fh.metadata['compression']
encr_alg = fh.metadata['encryption']
-
+
if compr_alg == 'BZIP2':
decompressor = bz2.BZ2Decompressor()
elif compr_alg == 'LZMA':
@@ -651,7 +624,11 @@ class BetterBackend(AbstractBackend, metaclass=ABCDocstMeta):
decompressor = None
else:
raise RuntimeError('Unsupported compression: %s' % compr_alg)
-
+
+ # If we've come this far, we want to emit a warning if the object
+ # has not been read completely on close().
+ checksum_warning = True
+
if encr_alg == 'AES':
fh = LegacyDecryptDecompressFilter(fh, self.passphrase, decompressor)
else:
@@ -659,15 +636,15 @@ class BetterBackend(AbstractBackend, metaclass=ABCDocstMeta):
fh = DecryptFilter(fh, self.passphrase)
elif encr_alg != 'None':
raise RuntimeError('Unsupported encryption: %s' % encr_alg)
-
+
if decompressor:
fh = DecompressFilter(fh, decompressor)
-
+
fh.metadata = metadata
except:
- fh.close()
+ fh.close(checksum_warning=checksum_warning)
raise
-
+
return fh
@copy_ancestor_docstring
@@ -726,17 +703,21 @@ class BetterBackend(AbstractBackend, metaclass=ABCDocstMeta):
@copy_ancestor_docstring
def delete_multi(self, keys, force=False):
return self.backend.delete_multi(keys, force=force)
-
+
@copy_ancestor_docstring
def list(self, prefix=''):
return self.backend.list(prefix)
@copy_ancestor_docstring
- def copy(self, src, dest):
+ def copy(self, src, dest, metadata=None):
+ if metadata is not None:
+ raise RuntimeError('Not yet supported')
return self.backend.copy(src, dest)
@copy_ancestor_docstring
- def rename(self, src, dest):
+ def rename(self, src, dest, metadata=None):
+ if metadata is not None:
+ raise RuntimeError('Not yet supported')
return self.backend.rename(src, dest)
@copy_ancestor_docstring
@@ -749,7 +730,7 @@ class CompressFilter(object):
def __init__(self, fh, compr):
'''Initialize
-
+
*fh* should be a file-like object. *decomp* should be a fresh compressor
instance with a *compress* method.
'''
@@ -769,13 +750,16 @@ class CompressFilter(object):
self.obj_size += len(buf)
def close(self):
- assert not self.closed
- buf = self.compr.flush()
- if buf:
- self.fh.write(buf)
- self.obj_size += len(buf)
+ # There may be errors when calling fh.close(), so we make sure that a
+ # repeated call is forwarded to fh.close(), even if we already cleaned
+ # up.
+ if not self.closed:
+ buf = self.compr.flush()
+ if buf:
+ self.fh.write(buf)
+ self.obj_size += len(buf)
+ self.closed = True
self.fh.close()
- self.closed = True
def __enter__(self):
return self
@@ -795,7 +779,7 @@ class InputFilter(io.RawIOBase):
# blocksize
def readall(self):
"""Read until EOF, using multiple read() calls."""
-
+
res = bytearray()
while True:
data = self.read(BUFSIZE)
@@ -821,13 +805,19 @@ class InputFilter(io.RawIOBase):
b = bytearray(size)
len_ = self.readinto(b)
return b[:len_]
-
+
+ def discard_input(self):
+ while True:
+ buf = self.fh.read(BUFSIZE)
+ if not buf:
+ break
+
class DecompressFilter(InputFilter):
'''Decompress data while reading'''
def __init__(self, fh, decomp, metadata=None):
'''Initialize
-
+
*fh* should be a file-like object and may be unbuffered. *decomp* should
be a fresh decompressor instance with a *decompress* method.
'''
@@ -836,7 +826,7 @@ class DecompressFilter(InputFilter):
self.fh = fh
self.decomp = decomp
self.metadata = metadata
-
+
def read(self, size=-1):
'''Read up to *size* bytes
@@ -849,7 +839,7 @@ class DecompressFilter(InputFilter):
return self.readall()
elif size == 0:
return b''
-
+
buf = b''
while not buf:
buf = self.fh.read(size)
@@ -858,19 +848,17 @@ class DecompressFilter(InputFilter):
raise ChecksumError('Premature end of stream.')
if self.decomp.unused_data:
raise ChecksumError('Data after end of compressed stream')
+
return b''
try:
buf = decompress(self.decomp, buf)
except ChecksumError:
- # Still read the stream completely (so that in case of
- # an encrypted stream we check the HMAC).
- while True:
- buf = self.fh.read(BUFSIZE)
- if not buf:
- break
+ # Read rest of stream, so that we raise HMAC or MD5 error instead
+ # if problem is on lower layer
+ self.discard_input()
raise
-
+
return buf
def close(self):
@@ -889,7 +877,7 @@ class EncryptFilter(object):
def __init__(self, fh, passphrase, nonce):
'''Initialize
-
+
*fh* should be a file-like object.
'''
super().__init__()
@@ -909,9 +897,9 @@ class EncryptFilter(object):
def write(self, data):
'''Write *data*
-
+
len(data) must be < 2**32.
-
+
Every invocation of `write` generates a packet that contains both the
length of the data and the data, so the passed data should have
reasonable size (if the data is written in e.g. 4 byte chunks, it is
@@ -929,18 +917,21 @@ class EncryptFilter(object):
self.obj_size += len(buf2)
def close(self):
- assert not self.closed
-
- # Packet length of 0 indicates end of stream, only HMAC follows
- buf = struct.pack(b'<I', 0)
- self.hmac.update(buf)
- buf += self.hmac.digest()
- buf2 = self.cipher.encrypt(buf)
- assert len(buf) == len(buf2)
- self.fh.write(buf2)
- self.obj_size += len(buf2)
+ # There may be errors when calling fh.close(), so we make sure that a
+ # repeated call is forwarded to fh.close(), even if we already cleaned
+ # up.
+ if not self.closed:
+ # Packet length of 0 indicates end of stream, only HMAC follows
+ buf = struct.pack(b'<I', 0)
+ self.hmac.update(buf)
+ buf += self.hmac.digest()
+ buf2 = self.cipher.encrypt(buf)
+ assert len(buf) == len(buf2)
+ self.fh.write(buf2)
+ self.obj_size += len(buf2)
+ self.closed = True
+
self.fh.close()
- self.closed = True
def __enter__(self):
return self
@@ -957,14 +948,14 @@ class EncryptFilter(object):
class DecryptFilter(InputFilter):
'''Decrypt data while reading
-
+
Reader has to read the entire stream in order for HMAC
checking to work.
'''
def __init__(self, fh, passphrase, metadata=None):
'''Initialize
-
+
*fh* should be a file-like object that may be unbuffered.
'''
super().__init__()
@@ -974,7 +965,7 @@ class DecryptFilter(InputFilter):
self.remaining = 0 # Remaining length of current packet
self.metadata = metadata
self.hmac_checked = False
-
+
# Read nonce
len_ = struct.unpack(b'<B', fh.read(struct.calcsize(b'<B')))[0]
nonce = fh.read(len_)
@@ -988,7 +979,7 @@ class DecryptFilter(InputFilter):
if not isinstance(size, int) or size <= 0:
raise ValueError("Exact *size* required (got %d)" % size)
-
+
buf = self.fh.read(size)
if not buf:
raise ChecksumError('Premature end of stream.')
@@ -997,13 +988,13 @@ class DecryptFilter(InputFilter):
# cipher.decrypt refuses to work with anything but bytes
if not isinstance(buf, bytes):
buf = bytes(buf)
-
+
len_ = len(buf)
buf = self.cipher.decrypt(buf)
assert len(buf) == len_
-
+
return buf
-
+
def read(self, size=-1):
'''Read up to *size* bytes'''
@@ -1016,18 +1007,18 @@ class DecryptFilter(InputFilter):
# want to read b'' from the underlying fh repeatedly)
if self.hmac_checked:
return b''
-
+
outbuf = b''
inbuf = b''
while True:
-
+
# If all remaining data is part of the same packet, return it.
if inbuf and len(inbuf) <= self.remaining:
self.remaining -= len(inbuf)
self.hmac.update(inbuf)
outbuf += inbuf
break
-
+
# Otherwise keep reading until we have something to return
# but make sure not to stop in packet header (so that we don't
# cache the partially read header from one invocation to the next).
@@ -1042,7 +1033,7 @@ class DecryptFilter(InputFilter):
assert buf
inbuf += buf
continue
-
+
# Copy rest of current packet to output and start reading
# from next packet
outbuf += inbuf[:self.remaining]
@@ -1056,15 +1047,19 @@ class DecryptFilter(InputFilter):
while len(inbuf) < HMAC_SIZE:
# Don't read exactly the missing amount, we wan't to detect
# if there's extraneous data
- buf = self._read_and_decrypt(HMAC_SIZE)
+ buf = self._read_and_decrypt(HMAC_SIZE+1)
assert buf
inbuf += buf
-
+
if len(inbuf) > HMAC_SIZE or self.fh.read(1):
+ # Read rest of stream, so that we raise MD5 error instead
+ # if problem is on lower layer
+ self.discard_input()
raise ChecksumError('Extraneous data at end of object')
-
+
if not hmac.compare_digest(inbuf, self.hmac.digest()):
raise ChecksumError('HMAC mismatch')
+
self.hmac_checked = True
break
@@ -1082,14 +1077,14 @@ class DecryptFilter(InputFilter):
class LegacyDecryptDecompressFilter(io.RawIOBase):
'''Decrypt and Decompress data while reading
-
+
Reader has to read the entire stream in order for HMAC
checking to work.
'''
def __init__(self, fh, passphrase, decomp, metadata=None):
'''Initialize
-
+
*fh* should be a file-like object and may be unbuffered.
'''
super().__init__()
@@ -1108,20 +1103,26 @@ class LegacyDecryptDecompressFilter(io.RawIOBase):
self.cipher = aes_cipher(key)
self.hmac = hmac.new(key, digestmod=hashlib.sha256)
+ def discard_input(self):
+ while True:
+ buf = self.fh.read(BUFSIZE)
+ if not buf:
+ break
+
def _decrypt(self, buf):
# Work around https://bugs.launchpad.net/pycrypto/+bug/1256172
# cipher.decrypt refuses to work with anything but bytes
if not isinstance(buf, bytes):
buf = bytes(buf)
-
+
len_ = len(buf)
buf = self.cipher.decrypt(buf)
assert len(buf) == len_
return buf
-
+
def read(self, size=-1):
'''Read up to *size* bytes
-
+
This method is currently buggy and may also return *more*
than *size* bytes. Callers should be prepared to handle
that. This is because some of the used (de)compression modules
@@ -1137,7 +1138,7 @@ class LegacyDecryptDecompressFilter(io.RawIOBase):
while not buf:
buf = self.fh.read(size)
if not buf and not self.hmac_checked:
- if not hmac.compare_digest(self._decrypt(self.hash),
+ if not hmac.compare_digest(self._decrypt(self.hash),
self.hmac.digest()):
raise ChecksumError('HMAC mismatch')
elif self.decomp and self.decomp.unused_data:
@@ -1182,7 +1183,8 @@ def decompress(decomp, buf):
raise ChecksumError('Invalid compressed stream')
raise
except lzma.LZMAError as exc:
- if exc.args[0].lower().startswith('corrupt input data'):
+ if (exc.args[0].lower().startswith('corrupt input data')
+ or exc.args[0].startswith('Input format not supported')):
raise ChecksumError('Invalid compressed stream')
raise
except zlib.error as exc:
@@ -1195,7 +1197,7 @@ def encrypt(buf, passphrase, nonce):
'''Encrypt *buf*'''
key = sha256(passphrase + nonce)
- cipher = aes_cipher(key)
+ cipher = aes_cipher(key)
hmac_ = hmac.new(key, digestmod=hashlib.sha256)
hmac_.update(buf)
@@ -1215,7 +1217,7 @@ def decrypt(buf, passphrase):
nonce = fh.read(len_)
key = sha256(passphrase + nonce)
- cipher = aes_cipher(key)
+ cipher = aes_cipher(key)
hmac_ = hmac.new(key, digestmod=hashlib.sha256)
# Read (encrypted) hmac
@@ -1236,7 +1238,7 @@ class ObjectNotEncrypted(Exception):
'''
Raised by the backend if an object was requested from an encrypted
backend, but the object was stored without encryption.
-
+
We do not want to simply return the uncrypted object, because the
caller may rely on the objects integrity being cryptographically
verified.
@@ -1294,19 +1296,19 @@ class AuthenticationError(Exception):
def __str__(self):
return 'Access denied. Server said: %s' % self.msg
-
+
def aes_cipher(key):
'''Return AES cipher in CTR mode for *key*'''
-
- return AES.new(key, AES.MODE_CTR,
- counter=Counter.new(128, initial_value=0))
-
+
+ return AES.new(key, AES.MODE_CTR,
+ counter=Counter.new(128, initial_value=0))
+
def convert_legacy_metadata(meta):
# For legacy format, meta is always a dict
if not isinstance(meta, dict):
return
-
+
if ('encryption' in meta and
'compression' in meta):
return
@@ -1341,170 +1343,3 @@ def convert_legacy_metadata(meta):
if meta['compression'] == 'NONE':
meta['compression'] = 'None'
-
-
-def get_backend(options, plain=False):
- '''Return backend for given storage-url
-
- If *plain* is true, don't attempt to unlock and don't wrap into
- BetterBackend.
- '''
-
- return get_backend_factory(options, plain)()
-
-def get_backend_factory(options, plain=False):
- '''Return factory producing backend objects for given storage-url
-
- If *plain* is true, don't attempt to unlock and don't wrap into
- BetterBackend.
- '''
-
- hit = re.match(r'^([a-zA-Z0-9]+)://', options.storage_url)
- if not hit:
- raise QuietError('Unknown storage url: %s' % options.storage_url)
-
- backend_name = 's3ql.backends.%s' % hit.group(1)
- try:
- __import__(backend_name)
- except ImportError:
- raise QuietError('No such backend: %s' % hit.group(1))
-
- backend_class = getattr(sys.modules[backend_name], 'Backend')
-
- # Read authfile
- config = configparser.ConfigParser()
- if os.path.isfile(options.authfile):
- mode = os.stat(options.authfile).st_mode
- if mode & (stat.S_IRGRP | stat.S_IROTH):
- raise QuietError("%s has insecure permissions, aborting." % options.authfile)
- config.read(options.authfile)
-
- backend_login = None
- backend_passphrase = None
- fs_passphrase = None
- for section in config.sections():
- def getopt(name):
- try:
- return config.get(section, name)
- except configparser.NoOptionError:
- return None
-
- pattern = getopt('storage-url')
-
- if not pattern or not options.storage_url.startswith(pattern):
- continue
-
- backend_login = getopt('backend-login') or backend_login
- backend_passphrase = getopt('backend-password') or backend_passphrase
- fs_passphrase = getopt('fs-passphrase') or fs_passphrase
- if getopt('fs-passphrase') is None and getopt('bucket-passphrase') is not None:
- fs_passphrase = getopt('bucket-passphrase')
- log.warning("Warning: the 'bucket-passphrase' configuration option has been "
- "renamed to 'fs-passphrase'! Please update your authinfo file.")
-
- if not backend_login and backend_class.needs_login:
- if sys.stdin.isatty():
- backend_login = getpass("Enter backend login: ")
- else:
- backend_login = sys.stdin.readline().rstrip()
-
- if not backend_passphrase and backend_class.needs_login:
- if sys.stdin.isatty():
- backend_passphrase = getpass("Enter backend passphrase: ")
- else:
- backend_passphrase = sys.stdin.readline().rstrip()
-
- ssl_context = get_ssl_context(options)
- if ssl_context is None:
- proxy_env = 'http_proxy'
- else:
- proxy_env = 'https_proxy'
-
- if proxy_env in os.environ:
- proxy = os.environ[proxy_env]
- hit = re.match(r'^(https?://)?([a-zA-Z0-9.-]+)(:[0-9]+)?/?$', proxy)
- if not hit:
- raise QuietError('Unable to parse proxy setting %s=%r' %
- (proxy_env, proxy))
-
- if hit.group(1) == 'https://':
- log.warning('HTTPS connection to proxy is probably pointless and not supported, '
- 'will use standard HTTP', extra=LOG_ONCE)
-
- if hit.group(3):
- proxy_port = int(hit.group(3)[1:])
- else:
- proxy_port = 80
-
- proxy_host = hit.group(2)
- log.info('Using CONNECT proxy %s:%d', proxy_host, proxy_port,
- extra=LOG_ONCE)
- proxy = (proxy_host, proxy_port)
- else:
- proxy = None
-
- backend = backend_class(options.storage_url, backend_login, backend_passphrase,
- ssl_context, proxy=proxy)
- try:
- # Do not use backend.lookup(), this would use a HEAD request and
- # not provide any useful error messages if something goes wrong
- # (e.g. wrong credentials)
- backend.fetch('s3ql_passphrase')
-
- except DanglingStorageURLError as exc:
- raise QuietError(str(exc))
-
- except AuthorizationError:
- raise QuietError('No permission to access backend.')
-
- except AuthenticationError:
- raise QuietError('Invalid credentials (or skewed system clock?).')
-
- except NoSuchObject:
- encrypted = False
-
- else:
- encrypted = True
-
- finally:
- backend.close()
-
- if plain:
- return lambda: backend_class(options.storage_url, backend_login, backend_passphrase,
- ssl_context, proxy=proxy)
-
- if encrypted and not fs_passphrase:
- if sys.stdin.isatty():
- fs_passphrase = getpass("Enter file system encryption passphrase: ")
- else:
- fs_passphrase = sys.stdin.readline().rstrip()
- elif not encrypted:
- fs_passphrase = None
-
- if fs_passphrase is not None:
- fs_passphrase = fs_passphrase.encode('utf-8')
-
- if hasattr(options, 'compress'):
- compress = options.compress
- else:
- compress = ('lzma', 2)
-
- if not encrypted:
- return lambda: BetterBackend(None, compress,
- backend_class(options.storage_url, backend_login,
- backend_passphrase, ssl_context=ssl_context,
- proxy=proxy))
-
- tmp_backend = BetterBackend(fs_passphrase, compress, backend)
-
- try:
- data_pw = tmp_backend['s3ql_passphrase']
- except ChecksumError:
- raise QuietError('Wrong file system passphrase')
- finally:
- tmp_backend.close()
-
- return lambda: BetterBackend(data_pw, compress,
- backend_class(options.storage_url, backend_login,
- backend_passphrase, ssl_context=ssl_context,
- proxy=proxy))
diff --git a/src/s3ql/backends/gs.py b/src/s3ql/backends/gs.py
index 6538009..e9d39e4 100644
--- a/src/s3ql/backends/gs.py
+++ b/src/s3ql/backends/gs.py
@@ -6,10 +6,17 @@ Copyright (C) Nikolaus Rath <Nikolaus@rath.org>
This program can be distributed under the terms of the GNU GPLv3.
'''
-from . import s3c
from ..logging import logging # Ensure use of custom logger class
-from s3ql.common import QuietError
+from . import s3c
+from .s3c import C_DAY_NAMES, C_MONTH_NAMES, HTTPError, S3Error
+from ..common import QuietError
+from .common import AuthenticationError
+from .. import oauth_client
+from dugong import CaseInsensitiveDict, HTTPConnection
+from urllib.parse import urlencode
import re
+import json
+import time
# Pylint goes berserk with false positives
#pylint: disable=E1002,E1101,W0201
@@ -18,29 +25,53 @@ log = logging.getLogger(__name__)
class Backend(s3c.Backend):
"""A backend to store data in Google Storage
-
+
This class uses standard HTTP connections to connect to GS.
-
+
The backend guarantees immediate get consistency and eventual list
consistency.
"""
use_expect_100c = False
-
+ xml_ns_prefix = '{http://doc.s3.amazonaws.com/2006-03-01}'
+
+ # We don't want to request an access token for each instance,
+ # because there is a limit on the total number of valid tokens.
+ # This class variable holds the mapping from refresh tokens to
+ # access tokens.
+ access_token = dict()
+
def __init__(self, storage_url, gs_key, gs_secret, ssl_context=None, proxy=None):
super().__init__(storage_url, gs_key, gs_secret, ssl_context=ssl_context,
proxy=proxy)
- self.xml_ns_prefix = '{http://doc.s3.amazonaws.com/2006-03-01}'
+ self.use_oauth2 = (gs_key == 'oauth2')
+
+ if self.use_oauth2:
+ self.hdr_prefix = 'x-goog-'
@staticmethod
def _parse_storage_url(storage_url, ssl_context):
+ # Special case for unit testing against local mock server
+ hit = re.match(r'^gs://!unittest!'
+ r'([^/:]+)' # Hostname
+ r':([0-9]+)' # Port
+ r'/([^/]+)' # Bucketname
+ r'(?:/(.*))?$', # Prefix
+ storage_url)
+ if hit:
+ hostname = hit.group(1)
+ port = int(hit.group(2))
+ bucket_name = hit.group(3)
+ prefix = hit.group(4) or ''
+ return (hostname, port, bucket_name, prefix)
+
hit = re.match(r'^gs://([^/]+)(?:/(.*))?$', storage_url)
if not hit:
raise QuietError('Invalid storage URL')
bucket_name = hit.group(1)
-
+
# Dots in the bucket cause problems with SSL certificate validation,
# because server certificate is for *.commondatastorage.googleapis.com
# (which does not match e.g. a.b.commondatastorage.googleapis.com)
@@ -48,7 +79,7 @@ class Backend(s3c.Backend):
hostname = 'commondatastorage.googleapis.com'
else:
hostname = '%s.commondatastorage.googleapis.com' % bucket_name
-
+
prefix = hit.group(2) or ''
port = 443 if ssl_context else 80
return (hostname, port, bucket_name, prefix)
@@ -56,4 +87,90 @@ class Backend(s3c.Backend):
def __str__(self):
return 'Google Storage bucket %s, prefix %s' % (self.bucket_name, self.prefix)
-
+ def _authorize_request(self, method, path, headers, subres):
+ '''Add authorization information to *headers*'''
+
+ if not self.use_oauth2:
+ return super()._authorize_request(method, path, headers, subres)
+
+ headers['Authorization'] = 'Bearer ' + self.access_token[self.password]
+
+ now = time.gmtime()
+ headers['Date'] = ('%s, %02d %s %04d %02d:%02d:%02d GMT'
+ % (C_DAY_NAMES[now.tm_wday],
+ now.tm_mday,
+ C_MONTH_NAMES[now.tm_mon - 1],
+ now.tm_year, now.tm_hour,
+ now.tm_min, now.tm_sec))
+
+ def _get_access_token(self):
+ log.info('Requesting new access token')
+
+ headers = CaseInsensitiveDict()
+ headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'
+
+ body = urlencode({'client_id': oauth_client.CLIENT_ID,
+ 'client_secret': oauth_client.CLIENT_SECRET,
+ 'refresh_token': self.password,
+ 'grant_type': 'refresh_token' })
+
+ conn = HTTPConnection('accounts.google.com', 443, proxy=self.proxy,
+ ssl_context=self.ssl_context)
+ try:
+
+ conn.send_request('POST', '/o/oauth2/token', headers=headers,
+ body=body.encode('utf-8'))
+ resp = conn.read_response()
+
+ resp_json = None
+ if 'Content-Type' in resp.headers:
+ hit = re.match(r'application/json(?:; charset="(.+)")?$',
+ resp.headers['Content-Type'], re.IGNORECASE)
+ if hit:
+ charset = hit.group(1) or 'utf-8'
+ body = conn.readall().decode(charset)
+ resp_json = json.loads(body)
+
+ if 'error' in resp_json:
+ raise AuthenticationError(resp_json['error'])
+
+ if resp.status > 299 or resp.status < 200:
+ raise HTTPError(resp.status, resp.reason, resp.headers)
+
+ if 'access_token' not in resp_json:
+ raise RuntimeError('Unable to parse server response')
+
+ self.access_token[self.password] = resp_json['access_token']
+
+ finally:
+ conn.disconnect()
+
+ def _do_request(self, method, path, subres=None, query_string=None,
+ headers=None, body=None):
+
+ # When using OAuth2 and we have an access token, try to use
+ # it (and invalidate if expired)
+ if self.use_oauth2 and self.password in self.access_token:
+ try:
+ return super()._do_request(method, path, subres=subres, headers=headers,
+ query_string=query_string, body=body)
+ except HTTPError as exc:
+ if exc.status != 401:
+ raise
+ except S3Error as exc:
+ if exc.code != 'AuthenticationRequired':
+ raise
+ try:
+ del self.access_token[self.password]
+ except KeyError: # Mind multithreading..
+ pass
+
+ # If we use OAuth2 and don't have an access token, retrieve
+ # one
+ if self.use_oauth2 and self.password not in self.access_token:
+ self._get_access_token()
+
+ # Try request. If we are using OAuth2 and this fails, propagate
+ # the error (because we have just refreshed the access token)
+ return super()._do_request(method, path, subres=subres, headers=headers,
+ query_string=query_string, body=body)
diff --git a/src/s3ql/backends/local.py b/src/s3ql/backends/local.py
index 8a70a69..eed0d67 100644
--- a/src/s3ql/backends/local.py
+++ b/src/s3ql/backends/local.py
@@ -28,21 +28,20 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
def __init__(self, storage_url, backend_login, backend_pw,
ssl_context=None, proxy=None):
'''Initialize local backend
-
+
Login and password are ignored.
'''
# Unused argument
#pylint: disable=W0613
super().__init__()
- name = storage_url[len('local://'):]
- self.name = name
+ self.prefix = storage_url[len('local://'):]
- if not os.path.exists(name):
- raise DanglingStorageURLError(name)
+ if not os.path.exists(self.prefix):
+ raise DanglingStorageURLError(self.prefix)
def __str__(self):
- return 'local directory %s' % self.name
+ return 'local directory %s' % self.prefix
@copy_ancestor_docstring
def is_temp_failure(self, exc): #IGNORE:W0613
@@ -73,7 +72,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
fh = ObjectR(path)
except FileNotFoundError:
raise NoSuchObject(key)
-
+
try:
fh.metadata = pickle.load(fh)
except pickle.UnpicklingError as exc:
@@ -91,24 +90,16 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
# conflicts between parallel reads, the last one wins
tmpname = '%s#%d-%d' % (path, os.getpid(), _thread.get_ident())
- try:
- dest = ObjectW(tmpname)
- except FileNotFoundError:
- try:
- os.makedirs(os.path.dirname(path))
- except FileExistsError:
- # Another thread may have created the directory already
- pass
- dest = ObjectW(tmpname)
-
+ dest = ObjectW(tmpname)
os.rename(tmpname, path)
+
pickle.dump(metadata, dest, PICKLE_PROTOCOL)
return dest
@copy_ancestor_docstring
def clear(self):
- for name in os.listdir(self.name):
- path = os.path.join(self.name, name)
+ for name in os.listdir(self.prefix):
+ path = os.path.join(self.prefix, name)
if os.path.isdir(path):
shutil.rmtree(path)
else:
@@ -140,13 +131,13 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
if prefix:
base = os.path.dirname(self._key_to_path(prefix))
else:
- base = self.name
+ base = self.prefix
for (path, dirnames, filenames) in os.walk(base, topdown=True):
# Do not look in wrong directories
if prefix:
- rpath = path[len(self.name):] # path relative to base
+ rpath = path[len(self.prefix):] # path relative to base
prefix_l = ''.join(rpath.split('/'))
dirs_to_walk = list()
@@ -163,46 +154,40 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
yield key
@copy_ancestor_docstring
- def copy(self, src, dest):
+ def copy(self, src, dest, metadata=None):
+
path_src = self._key_to_path(src)
path_dest = self._key_to_path(dest)
- # Can't use shutil.copyfile() here, need to make
- # sure destination path exists
try:
- dest = open(path_dest, 'wb')
+ src = open(path_src, 'rb')
except FileNotFoundError:
- try:
- os.makedirs(os.path.dirname(path_dest))
- except FileExistsError:
- # Another thread may have created the directory already
- pass
- dest = open(path_dest, 'wb')
+ raise NoSuchObject(src)
+ dest = None
try:
- with open(path_src, 'rb') as src:
- shutil.copyfileobj(src, dest, BUFSIZE)
- except FileNotFoundError:
- raise NoSuchObject(src)
+ # By renaming, we make sure that there are no conflicts between
+ # parallel writes, the last one wins
+ tmpname = '%s#%d-%d' % (path_dest, os.getpid(), _thread.get_ident())
+ dest = ObjectW(tmpname)
+
+ if metadata is not None:
+ try:
+ pickle.load(src)
+ except pickle.UnpicklingError:
+ raise ChecksumError('Invalid metadata')
+ pickle.dump(metadata, dest, PICKLE_PROTOCOL)
+ shutil.copyfileobj(src, dest, BUFSIZE)
+ except:
+ if dest:
+ os.unlink(tmpname)
+ raise
+
finally:
+ src.close()
dest.close()
- @copy_ancestor_docstring
- def rename(self, src, dest):
- src_path = self._key_to_path(src)
- dest_path = self._key_to_path(dest)
- if not os.path.exists(src_path):
- raise NoSuchObject(src)
-
- try:
- os.rename(src_path, dest_path)
- except FileNotFoundError:
- try:
- os.makedirs(os.path.dirname(dest_path))
- except FileExistsError:
- # Another thread may have created the directory already
- pass
- os.rename(src_path, dest_path)
+ os.rename(tmpname, path_dest)
def _key_to_path(self, key):
'''Return path for given key'''
@@ -213,10 +198,10 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
key = escape(key)
if not key.startswith('s3ql_data_'):
- return os.path.join(self.name, key)
+ return os.path.join(self.prefix, key)
no = key[10:]
- path = [ self.name, 's3ql_data_']
+ path = [ self.prefix, 's3ql_data_']
for i in range(0, len(no), 3):
path.append(no[:i])
path.append(key)
@@ -254,18 +239,36 @@ class ObjectR(io.FileIO):
super().__init__(name)
self.metadata = metadata
+ def close(self, checksum_warning=True):
+ '''Close object
+
+ The *checksum_warning* parameter is ignored.
+ '''
+ super().close()
+
class ObjectW(object):
'''A local storage object opened for writing'''
def __init__(self, name):
super().__init__()
- # Inherit from io.FileIO rather than io.BufferedReader to disable buffering. Default buffer
- # size is ~8 kB (http://docs.python.org/3/library/functions.html#open), but backends are
- # almost always only accessed by block_cache and stream_read_bz2/stream_write_bz2, which all
- # use the much larger s3ql.common.BUFSIZE
- self.fh = open(name, 'wb', buffering=0)
-
+ # Default buffer size is ~8 kB
+ # (http://docs.python.org/3/library/functions.html#open), but backends
+ # are almost always only accessed by block_cache and
+ # stream_read_bz2/stream_write_bz2, which all use the much larger
+ # s3ql.common.BUFSIZE - so we may just as well disable buffering.
+
+ # Create parent directories as needed
+ try:
+ self.fh = open(name, 'wb', buffering=0)
+ except FileNotFoundError:
+ try:
+ os.makedirs(os.path.dirname(name))
+ except FileExistsError:
+ # Another thread may have created the directory already
+ pass
+ self.fh = open(name, 'wb', buffering=0)
+
self.obj_size = 0
self.closed = False
diff --git a/src/s3ql/backends/rackspace.py b/src/s3ql/backends/rackspace.py
index b4d9272..e7b77fe 100644
--- a/src/s3ql/backends/rackspace.py
+++ b/src/s3ql/backends/rackspace.py
@@ -37,6 +37,5 @@ class Backend(swiftks.Backend):
port = 443
else:
port = 80
-
- return ('auth.api.rackspacecloud.com', port, region, containername, prefix)
+ return ('auth.api.rackspacecloud.com', port, region, containername, prefix)
diff --git a/src/s3ql/backends/s3.py b/src/s3ql/backends/s3.py
index 9522086..8f395b3 100644
--- a/src/s3ql/backends/s3.py
+++ b/src/s3ql/backends/s3.py
@@ -10,7 +10,7 @@ from ..logging import logging # Ensure use of custom logger class
from . import s3c
from .s3c import get_S3Error
from .common import NoSuchObject, retry
-from ..common import QuietError, BUFSIZE
+from ..common import QuietError
from ..inherit_docstrings import copy_ancestor_docstring
from xml.sax.saxutils import escape as xml_escape
import re
@@ -22,17 +22,17 @@ MAX_KEYS = 1000
# Pylint goes berserk with false positives
#pylint: disable=E1002,E1101
-
+
class Backend(s3c.Backend):
"""A backend to store data in Amazon S3
-
+
This class uses standard HTTP connections to connect to S3.
-
+
The backend guarantees get after create consistency, i.e. a newly created
object will be immediately retrievable. Additional consistency guarantees
- may or may not be available and can be queried for with instance methods.
+ may or may not be available and can be queried for with instance methods.
"""
-
+
def __init__(self, storage_url, login, password, ssl_context=None,
proxy=None):
super().__init__(storage_url, login, password, proxy=proxy,
@@ -45,11 +45,11 @@ class Backend(s3c.Backend):
raise QuietError('Invalid storage URL')
bucket_name = hit.group(1)
-
+
# http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/BucketRestrictions.html
if not re.match('^[a-z0-9][a-z0-9.-]{1,60}[a-z0-9]$', bucket_name):
raise QuietError('Invalid bucket name.')
-
+
# Dots in the bucket cause problems with SSL certificate validation,
# because server certificate is for *.s3.amazonaws.com (which does not
# match e.g. a.b.s3.amazonaws.com). However, when using path based
@@ -63,7 +63,7 @@ class Backend(s3c.Backend):
'This is purely Amazon\'s fault, see '
'https://forums.aws.amazon.com/thread.jspa?threadID=130560')
hostname = '%s.s3.amazonaws.com' % bucket_name
-
+
prefix = hit.group(2) or ''
port = 443 if ssl_context else 80
return (hostname, port, bucket_name, prefix)
@@ -93,12 +93,12 @@ class Backend(s3c.Backend):
body.append('</Delete>')
body = '\n'.join(body).encode('utf-8')
headers = { 'content-type': 'text/xml; charset=utf-8' }
-
+
resp = self._do_request('POST', '/', subres='delete', body=body, headers=headers)
try:
root = self._parse_xml_response(resp)
ns_p = self.xml_ns_prefix
-
+
error_tags = root.findall(ns_p + 'Error')
if not error_tags:
# No errors occured, everything has been deleted
@@ -115,10 +115,10 @@ class Backend(s3c.Backend):
if log.isEnabledFor(logging.DEBUG):
for errtag in error_tags:
- log.debug('Delete %s failed with %s',
+ log.debug('Delete %s failed with %s',
errtag.findtext(ns_p + 'Key')[offset:],
errtag.findtext(ns_p + 'Code'))
-
+
# If *force*, just modify the passed list and return without
# raising an exception, otherwise raise exception for the first error
if force:
diff --git a/src/s3ql/backends/s3c.py b/src/s3ql/backends/s3c.py
index 79fb506..d780e60 100644
--- a/src/s3ql/backends/s3c.py
+++ b/src/s3ql/backends/s3c.py
@@ -8,17 +8,18 @@ This program can be distributed under the terms of the GNU GPLv3.
from ..logging import logging # Ensure use of custom logger class
from ..common import QuietError, PICKLE_PROTOCOL, ChecksumError, BUFSIZE
-from .common import (AbstractBackend, NoSuchObject, retry, AuthorizationError,
+from .common import (AbstractBackend, NoSuchObject, retry, AuthorizationError,
AuthenticationError, DanglingStorageURLError, retry_generator)
from ..inherit_docstrings import (copy_ancestor_docstring, prepend_ancestor_docstring,
ABCDocstMeta)
from io import BytesIO
from shutil import copyfileobj
-from dugong import HTTPConnection, is_temp_network_error, BodyFollowing, CaseInsensitiveDict
+from dugong import (HTTPConnection, is_temp_network_error, BodyFollowing, CaseInsensitiveDict,
+ UnsupportedResponse)
from base64 import b64encode, b64decode
from email.utils import parsedate_tz, mktime_tz
from urllib.parse import urlsplit
-from xml.etree import ElementTree
+import defusedxml.cElementTree as ElementTree
import hashlib
import os
import hmac
@@ -37,9 +38,9 @@ log = logging.getLogger(__name__)
class Backend(AbstractBackend, metaclass=ABCDocstMeta):
"""A backend to stored data in some S3 compatible storage service.
-
+
This class uses standard HTTP connections to connect to GS.
-
+
The backend guarantees only immediate get after create consistency.
If the *expect_100c* class variable is True, the 'Expect: 100-continue'
@@ -47,6 +48,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
"""
use_expect_100c = True
+ xml_ns_prefix = '{http://s3.amazonaws.com/doc/2006-03-01/}'
def __init__(self, storage_url, login, password, ssl_context=None,
proxy=None):
@@ -54,7 +56,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
*ssl_context* may be a `ssl.SSLContext` instance or *None*.
'''
-
+
super().__init__()
(host, port, bucket_name, prefix) = self._parse_storage_url(storage_url, ssl_context)
@@ -69,7 +71,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
self.password = password
self.login = login
- self.xml_ns_prefix = '{http://s3.amazonaws.com/doc/2006-03-01/}'
+ self.hdr_prefix = 'x-amz-'
@copy_ancestor_docstring
def reset(self):
@@ -80,13 +82,13 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
@staticmethod
def _parse_storage_url(storage_url, ssl_context):
'''Extract information from storage URL
-
+
Return a tuple * (host, port, bucket_name, prefix) * .
'''
hit = re.match(r'^[a-zA-Z0-9]+://' # Backend
r'([^/:]+)' # Hostname
- r'(?::([0-9]+))?' # Port
+ r'(?::([0-9]+))?' # Port
r'/([^/]+)' # Bucketname
r'(?:/(.*))?$', # Prefix
storage_url)
@@ -113,17 +115,21 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
@copy_ancestor_docstring
def is_temp_failure(self, exc): #IGNORE:W0613
- if isinstance(exc, (InternalError, BadDigestError, IncompleteBodyError,
- RequestTimeoutError, OperationAbortedError, SlowDownError,
+ if isinstance(exc, (InternalError, BadDigestError, IncompleteBodyError,
+ RequestTimeoutError, OperationAbortedError, SlowDownError,
RequestTimeTooSkewedError)):
return True
elif is_temp_network_error(exc):
return True
-
- elif isinstance(exc, HTTPError) and exc.status >= 500 and exc.status <= 599:
+
+ # In doubt, we retry on 5xx. However, there are some codes
+ # where retry is definitely not desired.
+ elif (isinstance(exc, HTTPError)
+ and exc.status >= 500 and exc.status <= 599
+ and exc.status not in (501,505,508,510,511,523)):
return True
-
+
return False
def _dump_response(self, resp, body=None):
@@ -134,23 +140,28 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
'''
if body is None:
- body = self.conn.read(2048)
- if body:
- self.conn.discard()
+ try:
+ body = self.conn.read(2048)
+ if body:
+ self.conn.discard()
+ except UnsupportedResponse:
+ log.warning('Unsupported response, trying to retrieve data from raw socket!')
+ body = self.conn.read_raw(2048)
+ self.conn.close()
else:
body = body[:2048]
-
+
return '%d %s\n%s\n\n%s' % (resp.status, resp.reason,
'\n'.join('%s: %s' % x for x in resp.headers.items()),
body.decode('utf-8', errors='backslashreplace'))
-
+
def _assert_empty_response(self, resp):
'''Assert that current response body is empty'''
buf = self.conn.read(2048)
if not buf:
return # expected
-
+
# Log the problem
self.conn.discard()
log.error('Unexpected server response. Expected nothing, got:\n'
@@ -171,7 +182,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
pass
else:
raise NoSuchObject(key)
-
+
@retry_generator
@copy_ancestor_docstring
def list(self, prefix='', start_after=''):
@@ -232,7 +243,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
else:
raise
- return extractmeta(resp)
+ return self._extractmeta(resp)
@retry
@copy_ancestor_docstring
@@ -262,7 +273,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
except NoSuchKeyError:
raise NoSuchObject(key)
- return ObjectR(key, resp, self, extractmeta(resp))
+ return ObjectR(key, resp, self, self._extractmeta(resp))
@prepend_ancestor_docstring
def open_write(self, key, metadata=None, is_compressed=False):
@@ -273,6 +284,13 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
log.debug('open_write(%s): start', key)
+ headers = CaseInsensitiveDict()
+ self._add_meta_headers(headers, metadata)
+
+ return ObjectW(key, self, headers)
+
+ def _add_meta_headers(self, headers, metadata):
+
# We don't store the metadata keys directly, because HTTP headers
# are case insensitive (so the server may change capitalization)
# and we may run into length restrictions.
@@ -280,24 +298,29 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
chunksize = 255
i = 0
- headers = CaseInsensitiveDict()
- headers['x-amz-meta-format'] = 'pickle'
+ headers[self.hdr_prefix + 'meta-format'] = 'pickle'
while i*chunksize < len(meta_buf):
- headers['x-amz-meta-data-%02d' % i] = meta_buf[i*chunksize:(i+1)*chunksize]
+ headers[self.hdr_prefix +
+ 'meta-data-%02d' % i] = meta_buf[i*chunksize:(i+1)*chunksize]
i += 1
- return ObjectW(key, self, headers)
-
-
@retry
@copy_ancestor_docstring
- def copy(self, src, dest):
+ def copy(self, src, dest, metadata=None):
log.debug('copy(%s, %s): start', src, dest)
+ headers = CaseInsensitiveDict()
+ headers[self.hdr_prefix + 'copy-source'] = \
+ '/%s/%s%s' % (self.bucket_name, self.prefix, src)
+
+ if metadata is None:
+ headers[self.hdr_prefix + 'metadata-directive'] = 'COPY'
+ else:
+ headers[self.hdr_prefix + 'metadata-directive'] = 'REPLACE'
+ self._add_meta_headers(headers, metadata)
+
try:
- self._do_request('PUT', '/%s%s' % (self.prefix, dest),
- headers={ 'x-amz-copy-source': '/%s/%s%s' % (self.bucket_name,
- self.prefix, src)})
+ self._do_request('PUT', '/%s%s' % (self.prefix, dest), headers=headers)
self.conn.discard()
except NoSuchKeyError:
raise NoSuchObject(src)
@@ -314,13 +337,12 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
if isinstance(body, (bytes, bytearray, memoryview)):
headers['Content-MD5'] = md5sum_b64(body)
-
+
redirect_count = 0
+ this_method = method
while True:
- resp = self._send_request(method, path, headers=headers, subres=subres,
+ resp = self._send_request(this_method, path, headers=headers, subres=subres,
query_string=query_string, body=body)
- log.debug('status: %d, request-id: %s', resp.status,
- resp.headers['x-amz-request-id'])
if (resp.status < 300 or resp.status > 399):
break
@@ -351,45 +373,81 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
self.conn = self._get_conn()
else:
raise RuntimeError('Redirect to different path on same host')
-
- # ..but endpoint may also be hidden in message body..
- else:
- # If we got a HEAD response, the server cannot transmit the
- # request body with the endpoint
- if method == 'HEAD':
- assert self.conn.read(1) == b''
- raise HTTPError(resp.status, resp.reason, resp.headers)
+ # ..but endpoint may also be hidden in message body.
+ # If we have done a HEAD request, we have to change to GET
+ # to actually retrieve the body.
+ elif resp.method == 'HEAD':
+ log.debug('Switching from HEAD to GET to read redirect body')
+ this_method = 'GET'
+
+ # Try to read new URL from request body
+ else:
tree = self._parse_xml_response(resp)
new_url = tree.findtext('Endpoint')
if not new_url:
- raise get_S3Error(tree.findtext('Code'), tree.findtext('Message'))
+ raise get_S3Error(tree.findtext('Code'), tree.findtext('Message'),
+ resp.headers)
self.hostname = new_url
self.conn.disconnect()
self.conn = self._get_conn()
-
- log.info('_do_request(): redirected to %s', new_url)
+
+ # Update method
+ this_method = method
+
+ log.info('_do_request(): redirected to %s', self.conn.hostname)
if body and not isinstance(body, (bytes, bytearray, memoryview)):
body.seek(0)
- # Success
+ # At the end, the request should have gone out with the right
+ # method
+ if this_method != method:
+ raise RuntimeError('Dazed and confused - HEAD fails but GET works?')
+
+ # Success
if resp.status >= 200 and resp.status <= 299:
return resp
+ # Error
+ self._parse_error_response(resp)
+
+ def _parse_error_response(self, resp):
+ '''Handle error response from server
+
+ Try to raise most-specific exception.
+ '''
+
+ # Note that even though the final server backend may guarantee to always
+ # deliver an XML document body with a detailed error message, we may
+ # also get errors from intermediate proxies.
+ content_type = resp.headers['Content-Type']
+
# If method == HEAD, server must not return response body
# even in case of errors
- if method.upper() == 'HEAD':
+ if resp.method.upper() == 'HEAD':
assert self.conn.read(1) == b''
raise HTTPError(resp.status, resp.reason, resp.headers)
- # Error
- tree = self._parse_xml_response(resp)
- raise get_S3Error(tree.findtext('Code'), tree.findtext('Message'))
+ # If not XML, do the best we can
+ if not XML_CONTENT_RE.match(content_type):
+ self.conn.discard()
+ raise HTTPError(resp.status, resp.reason, resp.headers)
+
+ # We don't stream the data into the parser because we want
+ # to be able to dump a copy if the parsing fails.
+ body = self.conn.readall()
+ try:
+ tree = ElementTree.parse(BytesIO(body)).getroot()
+ except:
+ log.error('Unable to parse server response as XML:\n%s',
+ self._dump_response(resp, body))
+ raise
+
+ raise get_S3Error(tree.findtext('Code'), tree.findtext('Message'), resp.headers)
-
def _parse_xml_response(self, resp):
'''Return element tree for XML response'''
@@ -417,7 +475,6 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
return tree
-
@prepend_ancestor_docstring
def clear(self):
"""
@@ -439,16 +496,11 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
def __str__(self):
return 's3c://%s/%s/%s' % (self.hostname, self.bucket_name, self.prefix)
- def _send_request(self, method, path, headers, subres=None, query_string=None, body=None):
- '''Add authentication and send request
-
- Returns the response object.
- '''
+ def _authorize_request(self, method, path, headers, subres):
+ '''Add authorization information to *headers*'''
# See http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html
- if not isinstance(headers, CaseInsensitiveDict):
- headers = CaseInsensitiveDict(headers)
-
+
# Date, can't use strftime because it's locale dependent
now = time.gmtime()
headers['Date'] = ('%s, %02d %s %04d %02d:%02d:%02d GMT'
@@ -482,7 +534,18 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
hashlib.sha1).digest()).decode()
headers['Authorization'] = 'AWS %s:%s' % (self.login, signature)
-
+
+ def _send_request(self, method, path, headers, subres=None, query_string=None, body=None):
+ '''Add authentication and send request
+
+ Returns the response object.
+ '''
+
+ if not isinstance(headers, CaseInsensitiveDict):
+ headers = CaseInsensitiveDict(headers)
+
+ self._authorize_request(method, path, headers, subres)
+
# Construct full path
if not self.hostname.startswith(self.bucket_name):
path = '/%s%s' % (self.bucket_name, path)
@@ -519,7 +582,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
assert resp.method == method
assert resp.path == path
return resp
-
+
except Exception as exc:
if is_temp_network_error(exc):
# We probably can't use the connection anymore
@@ -530,27 +593,63 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
def close(self):
self.conn.disconnect()
+ def _extractmeta(self, resp):
+ '''Extract metadata from HTTP response object'''
+
+ meta = dict()
+ pattern = re.compile(r'^%smeta-(.+)$' % re.escape(self.hdr_prefix),
+ re.IGNORECASE)
+ format_ = 'raw'
+ for (name, val) in resp.headers.items():
+ # HTTP headers are case-insensitive and pre 2.x S3QL versions metadata
+ # names verbatim (and thus loose capitalization info), so we force lower
+ # case (since we know that this is the original capitalization).
+ name = name.lower()
+
+ hit = pattern.search(name)
+ if not hit:
+ continue
+
+ if hit.group(1) == 'format':
+ format_ = val
+ else:
+ meta[hit.group(1)] = val
+
+ if format_ == 'pickle':
+ buf = ''.join(meta[x] for x in sorted(meta)
+ if x.startswith('data-'))
+ try:
+ return pickle.loads(b64decode(buf))
+ except pickle.UnpicklingError as exc:
+ if (isinstance(exc.args[0], str)
+ and exc.args[0].startswith('invalid load key')):
+ raise ChecksumError('Invalid metadata')
+ raise
+ else:
+ return meta
+
class ObjectR(object):
'''An S3 object open for reading'''
# NOTE: This class is used as a base class for the swift backend,
# so changes here should be checked for their effects on other
# backends.
-
+
def __init__(self, key, resp, backend, metadata=None):
self.key = key
self.resp = resp
+ self.closed = False
self.md5_checked = False
self.backend = backend
self.metadata = metadata
# False positive, hashlib *does* have md5 member
- #pylint: disable=E1101
+ #pylint: disable=E1101
self.md5 = hashlib.md5()
def read(self, size=None):
'''Read up to *size* bytes of object data
-
+
For integrity checking to work, this method has to be called until
it returns an empty string, indicating that all data has been read
(and verified).
@@ -560,57 +659,73 @@ class ObjectR(object):
return b''
buf = self.backend.conn.read(size)
+ self.md5.update(buf)
# Check MD5 on EOF
- if not buf and not self.md5_checked:
+ # (size == None implies EOF)
+ if (not buf or size is None) and not self.md5_checked:
etag = self.resp.headers['ETag'].strip('"')
self.md5_checked = True
if etag != self.md5.hexdigest():
- log.warning('ObjectR(%s).close(): MD5 mismatch: %s vs %s', self.key, etag,
- self.md5.hexdigest())
- raise BadDigestError('BadDigest', 'ETag header does not agree with calculated MD5')
-
- return buf
-
- self.md5.update(buf)
+ log.warning('MD5 mismatch for %s: %s vs %s',
+ self.key, etag, self.md5.hexdigest())
+ raise BadDigestError('BadDigest',
+ 'ETag header does not agree with calculated MD5')
return buf
def __enter__(self):
return self
def __exit__(self, *a):
+ self.close()
return False
- def close(self):
- '''Close object'''
+ def close(self, checksum_warning=True):
+ '''Close object
+
+ If *checksum_warning* is true, this will generate a warning message if
+ the object has not been fully read (because in that case the MD5
+ checksum cannot be checked).
+ '''
+
+ if self.closed:
+ return
+ self.closed = True
+
+ # If we have not read all the data, close the entire
+ # connection (otherwise we loose synchronization)
+ if not self.md5_checked:
+ if checksum_warning:
+ log.warning("Object closed prematurely, can't check MD5, and have to "
+ "reset connection")
+ self.backend.conn.disconnect()
- pass
class ObjectW(object):
'''An S3 object open for writing
-
+
All data is first cached in memory, upload only starts when
the close() method is called.
'''
-
+
# NOTE: This class is used as a base class for the swift backend,
# so changes here should be checked for their effects on other
# backends.
-
+
def __init__(self, key, backend, headers):
self.key = key
self.backend = backend
self.headers = headers
self.closed = False
self.obj_size = 0
-
+
# According to http://docs.python.org/3/library/functions.html#open
- # the buffer size is typically ~8 kB. We process data in much
+ # the buffer size is typically ~8 kB. We process data in much
# larger chunks, so buffering would only hurt performance.
- self.fh = tempfile.TemporaryFile(buffering=0)
+ self.fh = tempfile.TemporaryFile(buffering=0)
# False positive, hashlib *does* have md5 member
- #pylint: disable=E1101
+ #pylint: disable=E1101
self.md5 = hashlib.md5()
def write(self, buf):
@@ -632,7 +747,10 @@ class ObjectW(object):
log.debug('ObjectW(%s).close(): start', self.key)
- assert not self.closed
+ if self.closed:
+ # still call fh.close, may have generated an error before
+ self.fh.close()
+ return
self.fh.seek(0)
self.headers['Content-Type'] = 'application/octet-stream'
@@ -649,8 +767,8 @@ class ObjectW(object):
raise BadDigestError('BadDigest', 'MD5 mismatch for %s (received: %s, sent: %s)' %
(self.key, etag, self.md5.hexdigest()))
- self.fh.close()
self.closed = True
+ self.fh.close()
def __enter__(self):
return self
@@ -665,65 +783,52 @@ class ObjectW(object):
return self.obj_size
-def get_S3Error(code, msg):
+def get_S3Error(code, msg, headers=None):
'''Instantiate most specific S3Error subclass'''
# Special case
# http://code.google.com/p/s3ql/issues/detail?id=369
if code == 'Timeout':
- code = 'RequestTimeout'
+ code = 'RequestTimeout'
if code.endswith('Error'):
name = code
else:
name = code + 'Error'
- class_ = globals().get(name, S3Error)
-
- if not issubclass(class_, S3Error):
- return S3Error(code, msg)
-
- return class_(code, msg)
-
-def extractmeta(resp):
- '''Extract metadata from HTTP response object'''
-
- meta = dict()
- format_ = 'raw'
- for (name, val) in resp.headers.items():
- # HTTP headers are case-insensitive and pre 2.x S3QL versions metadata
- # names verbatim (and thus loose capitalization info), so we force lower
- # case (since we know that this is the original capitalization).
- name = name.lower()
-
- hit = re.match(r'^x-amz-meta-(.+)$', name, re.IGNORECASE)
- if not hit:
- continue
+ class_ = globals().get(name, S3Error)
- if hit.group(1).lower() == 'format':
- format_ = val
- else:
- meta[hit.group(1)] = val
+ if not issubclass(class_, S3Error):
+ return S3Error(code, msg, headers)
- if format_ == 'pickle':
- buf = ''.join(meta[x] for x in sorted(meta)
- if x.startswith('data-'))
- try:
- return pickle.loads(b64decode(buf))
- except pickle.UnpicklingError as exc:
- if (isinstance(exc.args[0], str)
- and exc.args[0].startswith('invalid load key')):
- raise ChecksumError('Invalid metadata')
- raise
- else:
- return meta
+ return class_(code, msg, headers)
def md5sum_b64(buf):
'''Return base64 encoded MD5 sum'''
-
+
return b64encode(hashlib.md5(buf).digest()).decode('ascii')
-
+
+def _parse_retry_after(header):
+ '''Parse headers for Retry-After value'''
+
+ hit = re.match(r'^\s*([0-9]+)\s*$', header)
+ if hit:
+ val = int(header)
+ else:
+ date = parsedate_tz(header)
+ if date is None:
+ log.warning('Unable to parse retry-after value: %s', header)
+ return None
+ val = mktime_tz(*date) - time.time()
+
+ if val > 300 or val < 0:
+ log.warning('Ignoring retry-after value of %.3f s, using 1 s instead', val)
+ val = 1
+
+ return val
+
+
class HTTPError(Exception):
'''
Represents an HTTP error returned by S3.
@@ -734,47 +839,32 @@ class HTTPError(Exception):
self.status = status
self.msg = msg
self.headers = headers
- self.retry_after = None
-
- if self.headers is not None:
- self._set_retry_after()
-
- def _set_retry_after(self):
- '''Parse headers for Retry-After value'''
-
- val = None
- for (k, v) in self.headers.items():
- if k.lower() == 'retry-after':
- hit = re.match(r'^\s*([0-9]+)\s*$', v)
- if hit:
- val = int(v)
- else:
- date = parsedate_tz(v)
- if date is None:
- log.warning('Unable to parse header: %s: %s', k, v)
- continue
- val = mktime_tz(*date) - time.time()
-
- if val is not None:
- if val > 300 or val < 0:
- log.warning('Ignoring invalid retry-after value of %.3f', val)
- else:
- self.retry_after = val
-
+
+ if headers and 'Retry-After' in headers:
+ self.retry_after = _parse_retry_after(headers['Retry-After'])
+ else:
+ self.retry_after = None
+
def __str__(self):
return '%d %s' % (self.status, self.msg)
+
class S3Error(Exception):
'''
Represents an error returned by S3. For possible codes, see
http://docs.amazonwebservices.com/AmazonS3/latest/API/ErrorResponses.html
'''
- def __init__(self, code, msg):
+ def __init__(self, code, msg, headers=None):
super().__init__(msg)
self.code = code
self.msg = msg
+ if headers and 'Retry-After' in headers:
+ self.retry_after = _parse_retry_after(headers['Retry-After'])
+ else:
+ self.retry_after = None
+
def __str__(self):
return '%s: %s' % (self.code, self.msg)
diff --git a/src/s3ql/backends/swift.py b/src/s3ql/backends/swift.py
index 0d455e4..4b7e4eb 100644
--- a/src/s3ql/backends/swift.py
+++ b/src/s3ql/backends/swift.py
@@ -25,6 +25,9 @@ import urllib.parse
log = logging.getLogger(__name__)
+#: Suffix to use when creating temporary objects
+TEMP_SUFFIX = '_tmp$oentuhuo23986konteuh1062$'
+
class Backend(AbstractBackend, metaclass=ABCDocstMeta):
"""A backend to store data in OpenStack Swift
@@ -133,17 +136,17 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
conn.send_request('GET', auth_path, headers=headers)
resp = conn.read_response()
- if resp.status == 412:
+ if resp.status in (404, 412):
log.debug('_refresh_auth(): auth to %s failed, trying next path', auth_path)
- self.conn.discard()
+ conn.discard()
continue
elif resp.status == 401:
- self.conn.discard()
+ conn.disconnect()
raise AuthorizationError(resp.reason)
elif resp.status > 299 or resp.status < 200:
- self.conn.discard()
+ conn.disconnect()
raise HTTPError(resp.status, resp.reason, resp.headers)
# Pylint can't infer SplitResult Types
@@ -242,7 +245,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
else:
raise HTTPError(resp.status, resp.reason, resp.headers)
-
+
def _assert_empty_response(self, resp):
'''Assert that current response body is empty'''
@@ -258,7 +261,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
buf)
raise RuntimeError('Unexpected server response')
-
+
def _dump_response(self, resp, body=None):
'''Return string representation of server response
@@ -272,7 +275,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
self.conn.discard()
else:
body = body[:2048]
-
+
return '%d %s\n%s\n\n%s' % (resp.status, resp.reason,
'\n'.join('%s: %s' % x for x in resp.headers.items()),
body.decode('utf-8', errors='backslashreplace'))
@@ -281,6 +284,8 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
@copy_ancestor_docstring
def lookup(self, key):
log.debug('lookup(%s)', key)
+ if key.endswith(TEMP_SUFFIX):
+ raise ValueError('Keys must not end with %s' % TEMP_SUFFIX)
try:
resp = self._do_request('HEAD', '/%s%s' % (self.prefix, key))
@@ -296,6 +301,8 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
@retry
@copy_ancestor_docstring
def get_size(self, key):
+ if key.endswith(TEMP_SUFFIX):
+ raise ValueError('Keys must not end with %s' % TEMP_SUFFIX)
log.debug('get_size(%s)', key)
try:
@@ -315,6 +322,8 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
@retry
@copy_ancestor_docstring
def open_read(self, key):
+ if key.endswith(TEMP_SUFFIX):
+ raise ValueError('Keys must not end with %s' % TEMP_SUFFIX)
try:
resp = self._do_request('GET', '/%s%s' % (self.prefix, key))
except HTTPError as exc:
@@ -324,13 +333,7 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
return ObjectR(key, resp, self, extractmeta(resp))
- @prepend_ancestor_docstring
- def open_write(self, key, metadata=None, is_compressed=False):
- """
- The returned object will buffer all data and only start the upload
- when its `close` method is called.
- """
- log.debug('open_write(%s): start', key)
+ def _add_meta_headers(self, headers, metadata):
# We don't store the metadata keys directly, because HTTP headers
# are case insensitive (so the server may change capitalization)
@@ -339,12 +342,25 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
chunksize = 255
i = 0
- headers = CaseInsensitiveDict()
headers['X-Object-Meta-Format'] = 'pickle'
while i*chunksize < len(meta_buf):
headers['X-Object-Meta-Data-%02d' % i] = meta_buf[i*chunksize:(i+1)*chunksize]
i += 1
+ @prepend_ancestor_docstring
+ def open_write(self, key, metadata=None, is_compressed=False):
+ """
+ The returned object will buffer all data and only start the upload
+ when its `close` method is called.
+ """
+ log.debug('open_write(%s): start', key)
+
+ if key.endswith(TEMP_SUFFIX):
+ raise ValueError('Keys must not end with %s' % TEMP_SUFFIX)
+
+ headers = CaseInsensitiveDict()
+ self._add_meta_headers(headers, metadata)
+
return ObjectW(key, self, headers)
@copy_ancestor_docstring
@@ -364,6 +380,8 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
@retry
@copy_ancestor_docstring
def delete(self, key, force=False):
+ if key.endswith(TEMP_SUFFIX):
+ raise ValueError('Keys must not end with %s' % TEMP_SUFFIX)
log.debug('delete(%s)', key)
try:
resp = self._do_request('DELETE', '/%s%s' % (self.prefix, key))
@@ -376,10 +394,23 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
@retry
@copy_ancestor_docstring
- def copy(self, src, dest):
+ def copy(self, src, dest, metadata=None):
+ if dest.endswith(TEMP_SUFFIX) or src.endswith(TEMP_SUFFIX):
+ raise ValueError('Keys must not end with %s' % TEMP_SUFFIX)
log.debug('copy(%s, %s): start', src, dest)
+
headers = CaseInsensitiveDict()
headers['X-Copy-From'] = '/%s/%s%s' % (self.container_name, self.prefix, src)
+
+ if metadata is not None:
+ # We can't do a direct copy, because during copy we can only update the
+ # metadata, but not replace it. Therefore, we have to make a full copy
+ # followed by a separate request to replace the metadata. To avoid an
+ # inconsistent intermediate state, we use a temporary object.
+ final_dest = dest
+ dest = final_dest + TEMP_SUFFIX
+ headers['X-Delete-After'] = '600'
+
try:
self._do_request('PUT', '/%s%s' % (self.prefix, dest), headers=headers)
self.conn.discard()
@@ -388,6 +419,21 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
raise NoSuchObject(src)
raise
+ if metadata is None:
+ return
+
+ # Update metadata
+ headers = CaseInsensitiveDict()
+ self._add_meta_headers(headers, metadata)
+ self._do_request('POST', '/%s%s' % (self.prefix, dest), headers=headers)
+ self.conn.discard()
+
+ # Rename object
+ headers = CaseInsensitiveDict()
+ headers['X-Copy-From'] = '/%s/%s%s' % (self.container_name, self.prefix, dest)
+ self._do_request('PUT', '/%s%s' % (self.prefix, final_dest), headers=headers)
+ self.conn.discard()
+
@retry_generator
@copy_ancestor_docstring
def list(self, prefix='', start_after='', batch_size=5000):
@@ -428,6 +474,8 @@ class Backend(AbstractBackend, metaclass=ABCDocstMeta):
for dataset in json.loads(self.conn.read().decode(hit.group(1))):
count += 1
marker = dataset['name']
+ if marker.endswith(TEMP_SUFFIX):
+ continue
yield marker[strip:]
except GeneratorExit:
diff --git a/src/s3ql/backends/swiftks.py b/src/s3ql/backends/swiftks.py
index 6d4f06b..ab3712a 100644
--- a/src/s3ql/backends/swiftks.py
+++ b/src/s3ql/backends/swiftks.py
@@ -25,10 +25,10 @@ class Backend(swift.Backend):
def __init__(self, storage_url, login, password, ssl_context=None, proxy=None):
# Unused argument
#pylint: disable=W0613
-
+
(host, port, region,
container_name, prefix) = self._parse_storage_url(storage_url, ssl_context)
-
+
self.hostname = host
self.port = port
self.region = region
@@ -41,7 +41,7 @@ class Backend(swift.Backend):
self.auth_prefix = None
self.conn = None
self.ssl_context = ssl_context
-
+
self._container_exists()
@staticmethod
@@ -50,7 +50,7 @@ class Backend(swift.Backend):
hit = re.match(r'^[a-zA-Z0-9]+://' # Backend
r'([^/:]+)' # Hostname
- r'(?::([0-9]+))?' # Port
+ r'(?::([0-9]+))?' # Port
r'/([a-zA-Z0-9._-]+):' # Region
r'([^/]+)' # Bucketname
r'(?:/(.*))?$', # Prefix
@@ -68,7 +68,7 @@ class Backend(swift.Backend):
region = hit.group(3)
containername = hit.group(4)
prefix = hit.group(5) or ''
-
+
return (hostname, port, region, containername, prefix)
@retry
@@ -76,7 +76,7 @@ class Backend(swift.Backend):
'''Obtain connection to server and authentication token'''
log.debug('_get_conn(): start')
-
+
conn = HTTPConnection(self.hostname, port=self.port, proxy=self.proxy,
ssl_context=self.ssl_context)
@@ -89,7 +89,7 @@ class Backend(swift.Backend):
else:
tenant = None
user = self.login
-
+
auth_body = { 'auth':
{ 'passwordCredentials':
{ 'username': user,
@@ -100,11 +100,11 @@ class Backend(swift.Backend):
conn.send_request('POST', '/v2.0/tokens', body=json.dumps(auth_body).encode('utf-8'),
headers=headers)
resp = conn.read_response()
-
+
if resp.status == 401:
self.conn.discard()
raise AuthorizationError(resp.reason)
-
+
elif resp.status > 299 or resp.status < 200:
self.conn.discard()
raise HTTPError(resp.status, resp.reason, resp.headers)
@@ -121,7 +121,7 @@ class Backend(swift.Backend):
if endpoint['region'] != self.region:
avail_regions.append(endpoint['region'])
continue
-
+
o = urlsplit(endpoint['publicURL'])
self.auth_prefix = urllib.parse.unquote(o.path)
conn.disconnect()
@@ -131,10 +131,8 @@ class Backend(swift.Backend):
if len(avail_regions) < 10:
raise QuietError('No accessible object storage service found in region %s'
- ' (available regions: %s)'
+ ' (available regions: %s)'
% (self.region, ', '.join(avail_regions)))
else:
raise QuietError('No accessible object storage service found in region %s'
% self.region)
-
-
diff --git a/src/s3ql/block_cache.py b/src/s3ql/block_cache.py
index f59c07c..8eefa15 100644
--- a/src/s3ql/block_cache.py
+++ b/src/s3ql/block_cache.py
@@ -35,7 +35,7 @@ class NoWorkerThreads(Exception):
Raised when trying to enqueue an object, but there
are no active consumer threads.
'''
-
+
pass
class Distributor(object):
@@ -51,10 +51,10 @@ class Distributor(object):
#: Number of threads waiting to consume an object
self.readers = 0
-
+
def put(self, obj, timeout=None):
'''Offer *obj* for consumption
-
+
The method blocks until another thread calls `get()` to consume the
object.
@@ -74,7 +74,7 @@ class Distributor(object):
if not self.cv.wait(timeout):
log.debug('timeout, returning')
return False
-
+
log.debug('got reader, enqueueing %s', obj)
self.readers -= 1
assert self.slot is None
@@ -82,23 +82,23 @@ class Distributor(object):
self.cv.notify_all() # notify readers
return True
-
+
def get(self):
'''Consume and return an object
-
+
The method blocks until another thread offers an object by calling the
- `put` method.
+ `put` method.
'''
with self.cv:
- self.readers += 1
+ self.readers += 1
self.cv.notify_all()
while self.slot is None:
log.debug('waiting for writer..')
self.cv.wait()
tmp = self.slot
self.slot = None
- self.cv.notify_all()
-
+ self.cv.notify_all()
+
return tmp
@@ -137,10 +137,10 @@ class SimpleEvent(object):
class CacheEntry(object):
"""An element in the block cache
-
+
Attributes:
-----------
-
+
:dirty: entry has been changed since it was last uploaded.
:size: current file size
:pos: current position in file
@@ -209,7 +209,7 @@ class CacheDict(OrderedDict):
An ordered dictionary designed to store CacheEntries.
Attributes:
-
+
:max_size: maximum size to which cache can grow
:max_entries: maximum number of entries in cache
:size: current size of all entries together
@@ -223,7 +223,7 @@ class CacheDict(OrderedDict):
def remove(self, key):
'''Remove *key* from disk and cache, update size'''
-
+
el = self.pop(key)
el.close()
el.unlink()
@@ -235,16 +235,16 @@ class CacheDict(OrderedDict):
class BlockCache(object):
"""Provides access to file blocks
-
+
This class manages access to file blocks. It takes care of creation,
uploading, downloading and deduplication.
-
+
This class uses the llfuse global lock. Methods which release the lock have
are marked as such in their docstring.
-
+
Attributes
----------
-
+
:path: where cached data is stored
:cache: ordered dictionary of cache entries
:mlock: MultiLock to synchronize access to objects and cache entries
@@ -272,9 +272,9 @@ class BlockCache(object):
self.transfer_completed = SimpleEvent()
# Will be initialized once threads are available
- self.to_upload = None
+ self.to_upload = None
self.to_remove = None
-
+
if not os.path.exists(self.path):
os.mkdir(self.path)
@@ -328,16 +328,16 @@ class BlockCache(object):
def _unlock_entry(self, inode, blockno, release_global=False,
noerror=False):
'''Release lock on cache entry'''
-
+
if release_global:
with lock_released:
self.mlock.release((inode, blockno), noerror=noerror)
else:
self.mlock.release((inode, blockno), noerror=noerror)
-
+
def destroy(self):
'''Clean up and stop worker threads
-
+
This method should be called without the global lock held.
'''
@@ -367,7 +367,7 @@ class BlockCache(object):
log.debug('waiting for upload threads...')
for t in self.upload_threads:
t.join()
-
+
log.debug('waiting for removal threads...')
for t in self.removal_threads:
t.join()
@@ -381,7 +381,7 @@ class BlockCache(object):
else:
log.error('Could not complete object removals, '
'no removal threads left alive')
-
+
self.to_upload = None
self.to_remove = None
self.upload_threads = None
@@ -391,7 +391,7 @@ class BlockCache(object):
log.debug('cleanup done.')
-
+
def _upload_loop(self):
'''Process upload queue'''
@@ -403,7 +403,7 @@ class BlockCache(object):
self._do_upload(*tmp)
-
+
def _do_upload(self, el, obj_id):
'''Upload object'''
@@ -442,7 +442,7 @@ class BlockCache(object):
# avoid this problem is to insert the hash into the blocks table
# *after* successfull upload. But this would open a window without
# de-duplication just to handle the special case of an upload
- # failing.
+ # failing.
#
# On the other hand, we also want to prevent future deduplication
# against this block: otherwise the next attempt to upload the same
@@ -456,12 +456,12 @@ class BlockCache(object):
# assigned to a new block, so the inode_blocks entries will
# refer to incorrect data.
#
-
+
with lock:
self.db.execute('UPDATE blocks SET hash=NULL WHERE obj_id=?',
(obj_id,))
raise
-
+
finally:
self.in_transit.remove(el)
self._unlock_obj(obj_id)
@@ -471,7 +471,7 @@ class BlockCache(object):
def wait(self):
'''Wait until an object has been uploaded
-
+
If there are no objects in transit, return immediately. This method
releases the global lock.
'''
@@ -484,7 +484,7 @@ class BlockCache(object):
def upload(self, el):
'''Upload cache entry `el` asynchronously
-
+
This method releases the global lock.
'''
@@ -503,7 +503,7 @@ class BlockCache(object):
log.debug('%s removed while waiting for lock', el)
self._unlock_entry(el.inode, el.blockno)
return
-
+
self.in_transit.add(el)
sha = hashlib.sha256()
el.seek(0)
@@ -543,7 +543,7 @@ class BlockCache(object):
# are available in db.
self.db.execute('INSERT OR REPLACE INTO inode_blocks (block_id, inode, blockno) '
'VALUES(?,?,?)', (block_id, el.inode, el.blockno))
-
+
with lock_released:
self._lock_obj(obj_id)
self._queue_upload((el, obj_id))
@@ -560,11 +560,11 @@ class BlockCache(object):
el.dirty = False
self.in_transit.remove(el)
self._unlock_entry(el.inode, el.blockno, release_global=True)
-
+
if old_block_id == block_id:
log.debug('upload(%s): unchanged, block_id=%d', el, block_id)
return
-
+
except:
self.in_transit.discard(el)
with lock_released:
@@ -590,7 +590,7 @@ class BlockCache(object):
break
else:
raise NoWorkerThreads('no upload threads')
-
+
def _queue_removal(self, obj):
'''Put *obj* into removal queue'''
@@ -601,13 +601,13 @@ class BlockCache(object):
pass
else:
return
-
+
for t in self.removal_threads:
if t.is_alive():
break
else:
raise NoWorkerThreads('no removal threads')
-
+
def _deref_block(self, block_id):
'''Decrease reference count for *block_id*
@@ -617,7 +617,7 @@ class BlockCache(object):
This method releases the global lock.
'''
-
+
refcount = self.db.get_val('SELECT refcount FROM blocks WHERE id=?', (block_id,))
if refcount > 1:
log.debug('decreased refcount for block: %d', block_id)
@@ -641,7 +641,7 @@ class BlockCache(object):
# transit itself. We can release it immediately after, because
# the object is no longer in the database.
log.debug('adding %d to removal queue', obj_id)
-
+
with lock_released:
self._lock_obj(obj_id)
self._unlock_obj(obj_id)
@@ -683,12 +683,12 @@ class BlockCache(object):
@contextmanager
def get(self, inode, blockno):
"""Get file handle for block `blockno` of `inode`
-
+
This method releases the global lock. The managed block, however,
is executed with the global lock acquired and MUST NOT release
it. This ensures that only one thread is accessing a given block
at a time.
-
+
Note: if `get` and `remove` are called concurrently, then it is
possible that a block that has been requested with `get` and
passed to `remove` for deletion will not be deleted.
@@ -712,7 +712,7 @@ class BlockCache(object):
self.cache.size += el.size - oldsize
finally:
self._unlock_entry(inode, blockno, release_global=True)
-
+
#log.debug('get(inode=%d, block=%d): end', inode, blockno)
def _get_entry(self, inode, blockno):
@@ -720,7 +720,7 @@ class BlockCache(object):
Assume that cache entry lock has been acquired.
'''
-
+
try:
el = self.cache[(inode, blockno)]
@@ -737,13 +737,13 @@ class BlockCache(object):
el = CacheEntry(inode, blockno, filename)
self.cache[(inode, blockno)] = el
return el
-
+
# Need to download corresponding object
obj_id = self.db.get_val('SELECT obj_id FROM blocks WHERE id=?', (block_id,))
log.debug('_get_entry(inode=%d, block=%d): downloading object %d..',
inode, blockno, obj_id)
el = CacheEntry(inode, blockno, filename)
- try:
+ try:
def do_read(fh):
el.seek(0)
el.truncate()
@@ -763,7 +763,7 @@ class BlockCache(object):
el.unlink()
el.close()
raise
-
+
self.cache[(inode, blockno)] = el
el.dirty = False # (writing will have set dirty flag)
self.cache.size += el.size
@@ -772,12 +772,12 @@ class BlockCache(object):
else:
#log.debug('_get_entry(inode=%d, block=%d): in cache', inode, blockno)
self.cache.move_to_end((inode, blockno), last=True) # move to head
-
+
return el
def expire(self):
"""Perform cache expiry
-
+
This method releases the global lock.
"""
@@ -789,7 +789,7 @@ class BlockCache(object):
while True:
need_size = self.cache.size - self.cache.max_size
need_entries = len(self.cache) - self.cache.max_entries
-
+
if need_size <= 0 and need_entries <= 0:
break
@@ -800,7 +800,7 @@ class BlockCache(object):
for el in list(self.cache.values()):
if need_size <= 0 and need_entries <= 0:
break
-
+
need_entries -= 1
need_size -= el.size
@@ -834,11 +834,11 @@ class BlockCache(object):
def remove(self, inode, start_no, end_no=None):
"""Remove blocks for `inode`
-
+
If `end_no` is not specified, remove just the `start_no` block.
Otherwise removes all blocks from `start_no` to, but not including,
- `end_no`.
-
+ `end_no`.
+
This method releases the global lock.
"""
@@ -868,7 +868,7 @@ class BlockCache(object):
finally:
self._unlock_entry(inode, blockno, release_global=True)
-
+
# Decrease block refcount
self._deref_block(block_id)
@@ -886,11 +886,11 @@ class BlockCache(object):
def commit(self):
"""Initiate upload of all dirty blocks
-
+
When the method returns, all blocks have been registered
- in the database (but the actual uploads may still be
+ in the database (but the actual uploads may still be
in progress).
-
+
This method releases the global lock.
"""
@@ -902,10 +902,10 @@ class BlockCache(object):
continue
self.upload(el) # Releases global lock
-
+
def clear(self):
"""Clear cache
-
+
This method releases the global lock.
"""
@@ -921,4 +921,3 @@ class BlockCache(object):
def __del__(self):
if len(self.cache) > 0:
raise RuntimeError("BlockManager instance was destroyed without calling destroy()!")
-
diff --git a/src/s3ql/common.py b/src/s3ql/common.py
index 1b622ac..0093955 100644
--- a/src/s3ql/common.py
+++ b/src/s3ql/common.py
@@ -18,6 +18,7 @@ import os
import posixpath
import stat
import sys
+import ssl
# Buffer size when writing objects
BUFSIZE = 64 * 1024
@@ -101,7 +102,7 @@ def stream_read_bz2(ifh, ofh):
if decompressor.unused_data or ifh.read(1) != b'':
raise ChecksumError('Data after end of bz2 stream')
-
+
def is_mounted(storage_url):
'''Try to determine if *storage_url* is mounted
@@ -125,10 +126,10 @@ def is_mounted(storage_url):
except subprocess.CalledProcessError:
log.warning('Warning! Unable to check if file system is mounted '
'(/proc/mounts missing and mount call failed)')
-
+
return False
-
+
class ChecksumError(Exception):
"""
Raised if there is a checksum error in the data that we received.
@@ -143,7 +144,7 @@ class ChecksumError(Exception):
def inode_for_path(path, conn):
"""Return inode of directory entry at `path`
-
+
Raises `KeyError` if the path does not exist.
"""
from .database import NoSuchRowError
@@ -167,7 +168,7 @@ def inode_for_path(path, conn):
def get_path(id_, conn, name=None):
"""Return a full path for inode `id_`.
-
+
If `name` is specified, it is appended at the very end of the
path (useful if looking up the path for file name with parent
inode).
@@ -212,10 +213,10 @@ def get_backend_cachedir(storage_url, cachedir):
os.mkdir(cachedir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
except PermissionError:
raise QuietError('No permission to create cache directory (%s)' % cachedir)
-
+
if not os.access(cachedir, os.R_OK | os.W_OK | os.X_OK):
raise QuietError('No permission to access cache directory (%s)' % cachedir)
-
+
return os.path.join(cachedir, _escape(storage_url))
@@ -237,7 +238,7 @@ def sha256_fh(fh):
def assert_s3ql_fs(path):
'''Raise `QuietError` if *path* is not on an S3QL file system
-
+
Returns name of the S3QL control file.
'''
@@ -256,33 +257,33 @@ def assert_s3ql_fs(path):
raise QuietError('%s is not on an S3QL file system' % path)
return ctrlfile
-
-
+
+
def assert_fs_owner(path, mountpoint=False):
'''Raise `QuietError` if user is not owner of S3QL fs at *path*
-
- Implicitly calls `assert_s3ql_fs` first. Returns name of the
+
+ Implicitly calls `assert_s3ql_fs` first. Returns name of the
S3QL control file.
-
+
If *mountpoint* is True, also call `assert_s3ql_mountpoint`, i.e.
fail if *path* is not the mount point of the file system.
'''
-
+
if mountpoint:
ctrlfile = assert_s3ql_mountpoint(path)
else:
ctrlfile = assert_s3ql_fs(path)
-
+
if os.stat(ctrlfile).st_uid != os.geteuid() and os.geteuid() != 0:
raise QuietError('Permission denied. %s is was not mounted by you '
'and you are not root.' % path)
return ctrlfile
-
+
def assert_s3ql_mountpoint(mountpoint):
'''Raise QuietError if *mountpoint* is not an S3QL mountpoint
-
- Implicitly calls `assert_s3ql_fs` first. Returns name of the
+
+ Implicitly calls `assert_s3ql_fs` first. Returns name of the
S3QL control file.
'''
@@ -291,3 +292,30 @@ def assert_s3ql_mountpoint(mountpoint):
raise QuietError('%s is not a mount point' % mountpoint)
return ctrlfile
+
+def get_ssl_context(options):
+ '''Construct SSLContext object from *options*
+
+ If SSL is disabled, return None.
+ '''
+
+ if options.no_ssl:
+ return None
+
+ # Best practice according to http://docs.python.org/3/library/ssl.html#protocol-versions
+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
+ context.options |= ssl.OP_NO_SSLv2
+ context.verify_mode = ssl.CERT_REQUIRED
+
+ path = options.ssl_ca_path
+ if path is None:
+ log.debug('Reading default CA certificates.')
+ context.set_default_verify_paths()
+ elif os.path.isfile(path):
+ log.debug('Reading CA certificates from file %s', path)
+ context.load_verify_locations(cafile=path)
+ else:
+ log.debug('Reading CA certificates from directory %s', path)
+ context.load_verify_locations(capath=path)
+
+ return context
diff --git a/src/s3ql/cp.py b/src/s3ql/cp.py
index cc8274b..9d9fe98 100644
--- a/src/s3ql/cp.py
+++ b/src/s3ql/cp.py
@@ -79,7 +79,7 @@ def main(args=None):
if os.path.ismount(options.source):
raise QuietError('%s is a mount point.' % options.source)
-
+
ctrlfile = assert_fs_owner(options.source)
try:
os.mkdir(options.target)
diff --git a/src/s3ql/ctrl.py b/src/s3ql/ctrl.py
index e929017..000eb75 100644
--- a/src/s3ql/ctrl.py
+++ b/src/s3ql/ctrl.py
@@ -101,7 +101,7 @@ def main(args=None):
PICKLE_PROTOCOL))
elif options.action == 'cachesize':
- llfuse.setxattr(ctrlfile, 'cachesize',
+ llfuse.setxattr(ctrlfile, 'cachesize',
pickle.dumps(options.cachesize * 1024, PICKLE_PROTOCOL))
diff --git a/src/s3ql/daemonize.py b/src/s3ql/daemonize.py
index 3f1bf84..631909f 100644
--- a/src/s3ql/daemonize.py
+++ b/src/s3ql/daemonize.py
@@ -84,5 +84,3 @@ def redirect_stream(system_stream, target_stream):
else:
target_fd = target_stream.fileno()
os.dup2(target_fd, system_stream.fileno())
-
-
diff --git a/src/s3ql/database.py b/src/s3ql/database.py
index 9cbdb80..0e2ab4c 100644
--- a/src/s3ql/database.py
+++ b/src/s3ql/database.py
@@ -24,18 +24,18 @@ sqlite_ver = tuple([ int(x) for x in apsw.sqlitelibversion().split('.') ])
if sqlite_ver < (3, 7, 0):
raise QuietError('SQLite version too old, must be 3.7.0 or newer!\n')
-
+
initsql = (
# WAL mode causes trouble with e.g. copy_tree, so we don't use it at the moment
- # (cf. http://article.gmane.org/gmane.comp.db.sqlite.general/65243).
- # However, if we start using it we must initiaze it *before* setting
+ # (cf. http://article.gmane.org/gmane.comp.db.sqlite.general/65243).
+ # However, if we start using it we must initiaze it *before* setting
# locking_mode to EXCLUSIVE, otherwise we can't switch the locking
# mode without first disabling WAL.
'PRAGMA synchronous = OFF',
'PRAGMA journal_mode = OFF',
#'PRAGMA synchronous = NORMAL',
#'PRAGMA journal_mode = WAL',
-
+
'PRAGMA foreign_keys = OFF',
'PRAGMA locking_mode = EXCLUSIVE',
'PRAGMA recursize_triggers = on',
@@ -49,16 +49,16 @@ class Connection(object):
'''
This class wraps an APSW connection object. It should be used instead of any
native APSW cursors.
-
+
It provides methods to directly execute SQL commands and creates apsw
cursors dynamically.
-
+
Instances are not thread safe. They can be passed between threads,
but must not be called concurrently.
-
+
Attributes
----------
-
+
:conn: apsw connection object
'''
@@ -83,8 +83,8 @@ class Connection(object):
return 0
def query(self, *a, **kw):
- '''Return iterator over results of given SQL statement
-
+ '''Return iterator over results of given SQL statement
+
If the caller does not retrieve all rows the iterator's close() method
should be called as soon as possible to terminate the SQL statement
(otherwise it may block execution of other statements). To this end,
@@ -120,7 +120,7 @@ class Connection(object):
def get_val(self, *a, **kw):
"""Execute statement and return first element of first result row.
-
+
If there is no result row, raises `NoSuchRowError`. If there is more
than one row, raises `NoUniqueValueError`.
"""
@@ -134,7 +134,7 @@ class Connection(object):
def get_row(self, *a, **kw):
"""Execute select statement and return first row.
-
+
If there are no result rows, raises `NoSuchRowError`. If there is more
than one result row, raises `NoUniqueValueError`.
"""
@@ -168,7 +168,7 @@ class Connection(object):
class NoUniqueValueError(Exception):
- '''Raised if get_val or get_row was called with a query
+ '''Raised if get_val or get_row was called with a query
that generated more than one result row.
'''
@@ -187,25 +187,25 @@ class ResultSet(object):
'''
Provide iteration over encapsulated apsw cursor. Additionally,
`ResultSet` instances may be used as context managers to terminate
- the query before all result rows have been retrieved.
+ the query before all result rows have been retrieved.
'''
-
+
def __init__(self, cur):
self.cur = cur
-
+
def __next__(self):
return next(self.cur)
-
+
def __iter__(self):
return self
-
+
def __enter__(self):
return self
-
+
def __exit__(self, exc_type, exc_value, traceback):
self.cur.close()
-
+
def close(self):
'''Terminate query'''
-
+
self.cur.close()
diff --git a/src/s3ql/deltadump.c b/src/s3ql/deltadump.c
index b5cbc8f..8fcf03a 100644
--- a/src/s3ql/deltadump.c
+++ b/src/s3ql/deltadump.c
@@ -1,4 +1,4 @@
-/* Generated by Cython 0.20 on Sat Mar 29 17:30:54 2014 */
+/* Generated by Cython 0.20.1post0 (Debian 0.20.1+git90-g0e6e38e-1+b1) on Sat Jun 28 12:18:28 2014 */
#define PY_SSIZE_T_CLEAN
#ifndef CYTHON_USE_PYLONG_INTERNALS
@@ -19,7 +19,7 @@
#elif PY_VERSION_HEX < 0x02040000
#error Cython requires Python 2.4+.
#else
-#define CYTHON_ABI "0_20"
+#define CYTHON_ABI "0_20_1post0"
#include <stddef.h> /* For offsetof */
#ifndef offsetof
#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
@@ -116,7 +116,7 @@
#if PY_MAJOR_VERSION < 3
#define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
- PyCode_New(a, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+ PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
#define __Pyx_DefaultClassType PyClass_Type
#else
#define __Pyx_BUILTIN_MODULE_NAME "builtins"
@@ -161,10 +161,16 @@
#define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u))
#define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i]))
#endif
+#if CYTHON_COMPILING_IN_PYPY
+ #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b)
+ #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b)
+#else
+ #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b)
+ #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
+ PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b))
+#endif
#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
-#define __Pyx_PyUnicode_Concat(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
- PyNumber_Add(a, b) : PyUnicode_Concat(a, b))
#if PY_MAJOR_VERSION >= 3
#define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b)
#else
@@ -231,7 +237,7 @@
#if PY_MAJOR_VERSION >= 3
#define PyBoolObject PyLongObject
#endif
-#if PY_VERSION_HEX < 0x03020000
+#if PY_VERSION_HEX < 0x030200A4
typedef long Py_hash_t;
#define __Pyx_PyInt_FromHash_t PyInt_FromLong
#define __Pyx_PyInt_AsHash_t PyInt_AsLong
@@ -310,6 +316,12 @@ static CYTHON_INLINE float __PYX_NAN() {
return value;
}
#endif
+#ifdef __cplusplus
+template<typename T>
+void __Pyx_call_destructor(T* x) {
+ x->~T();
+}
+#endif
#if PY_MAJOR_VERSION >= 3
@@ -387,7 +399,7 @@ static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t*
#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l)
#define __Pyx_PyBytes_FromString PyBytes_FromString
#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
-static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char*);
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
#if PY_MAJOR_VERSION < 3
#define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString
#define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
@@ -397,11 +409,11 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char*);
#endif
#define __Pyx_PyObject_AsSString(s) ((signed char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s))
-#define __Pyx_PyObject_FromUString(s) __Pyx_PyObject_FromString((char*)s)
-#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((char*)s)
-#define __Pyx_PyByteArray_FromUString(s) __Pyx_PyByteArray_FromString((char*)s)
-#define __Pyx_PyStr_FromUString(s) __Pyx_PyStr_FromString((char*)s)
-#define __Pyx_PyUnicode_FromUString(s) __Pyx_PyUnicode_FromString((char*)s)
+#define __Pyx_PyObject_FromUString(s) __Pyx_PyObject_FromString((const char*)s)
+#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((const char*)s)
+#define __Pyx_PyByteArray_FromUString(s) __Pyx_PyByteArray_FromString((const char*)s)
+#define __Pyx_PyStr_FromUString(s) __Pyx_PyStr_FromString((const char*)s)
+#define __Pyx_PyUnicode_FromUString(s) __Pyx_PyUnicode_FromString((const char*)s)
#if PY_MAJOR_VERSION < 3
static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
{
@@ -501,16 +513,11 @@ bad:
#endif
-#ifdef __GNUC__
- /* Test for GCC > 2.95 */
- #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
- #define likely(x) __builtin_expect(!!(x), 1)
- #define unlikely(x) __builtin_expect(!!(x), 0)
- #else /* __GNUC__ > 2 ... */
- #define likely(x) (x)
- #define unlikely(x) (x)
- #endif /* __GNUC__ > 2 ... */
-#else /* __GNUC__ */
+/* Test for GCC > 2.95 */
+#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))
+ #define likely(x) __builtin_expect(!!(x), 1)
+ #define unlikely(x) __builtin_expect(!!(x), 0)
+#else /* !__GNUC__ or GCC < 2.95 */
#define likely(x) (x)
#define unlikely(x) (x)
#endif /* __GNUC__ */
@@ -531,8 +538,8 @@ static const char *__pyx_f[] = {
};
/*--- Type declarations ---*/
-struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table;
struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table;
+struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table;
struct __pyx_opt_args_4s3ql_9deltadump_raise_from_errno;
/* "s3ql/deltadump.pyx":135
@@ -547,20 +554,17 @@ struct __pyx_opt_args_4s3ql_9deltadump_raise_from_errno {
PyObject *err_class;
};
-/* "s3ql/deltadump.pyx":390
- * fwrite(buf, len_, fp)
+/* "s3ql/deltadump.pyx":277
+ * s3ql_sqlite_options - apsw_sqlite_options))
*
- * def load_table(table, columns, db, fh, trx_rows=5000): # <<<<<<<<<<<<<<
- * '''Load *columns* of *table* from *fh*
+ * def dump_table(table, order, columns, db, fh): # <<<<<<<<<<<<<<
+ * '''Dump *columns* of *table* into *fh*
*
*/
-struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table {
+struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table {
PyObject_HEAD
- sqlite3_stmt *__pyx_v_begin_stmt;
- void *__pyx_v_buf;
int *__pyx_v_col_args;
int *__pyx_v_col_types;
- sqlite3_stmt *__pyx_v_commit_stmt;
FILE *__pyx_v_fp;
int64_t *__pyx_v_int64_prev;
sqlite3 *__pyx_v_sqlite3_db;
@@ -568,17 +572,20 @@ struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table {
};
-/* "s3ql/deltadump.pyx":275
- * s3ql_sqlite_options - apsw_sqlite_options))
+/* "s3ql/deltadump.pyx":395
+ * fwrite(buf, len_, fp)
*
- * def dump_table(table, order, columns, db, fh): # <<<<<<<<<<<<<<
- * '''Dump *columns* of *table* into *fh*
+ * def load_table(table, columns, db, fh, trx_rows=5000): # <<<<<<<<<<<<<<
+ * '''Load *columns* of *table* from *fh*
*
*/
-struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table {
+struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table {
PyObject_HEAD
+ sqlite3_stmt *__pyx_v_begin_stmt;
+ void *__pyx_v_buf;
int *__pyx_v_col_args;
int *__pyx_v_col_types;
+ sqlite3_stmt *__pyx_v_commit_stmt;
FILE *__pyx_v_fp;
int64_t *__pyx_v_int64_prev;
sqlite3 *__pyx_v_sqlite3_db;
@@ -664,6 +671,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject
static PyObject *__Pyx_GetBuiltinName(PyObject *name); /*proto*/
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); /*proto*/
+#else
+#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw)
+#endif
+
static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
@@ -699,10 +712,12 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
(ob)->ob_type == &PyFrozenSet_Type)
#define PySet_New(iterable) \
PyObject_CallFunctionObjArgs((PyObject *)&PySet_Type, (iterable), NULL)
-#define Pyx_PyFrozenSet_New(iterable) \
+#define PyFrozenSet_New(iterable) \
PyObject_CallFunctionObjArgs((PyObject *)&PyFrozenSet_Type, (iterable), NULL)
#define PySet_Size(anyset) \
PyObject_Size((anyset))
+#define PySet_GET_SIZE(anyset) \
+ PyObject_Size((anyset))
#define PySet_Contains(anyset, key) \
PySequence_Contains((anyset), (key))
#define PySet_Pop(set) \
@@ -740,7 +755,7 @@ static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int eq
static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/
-#if CYTHON_COMPILING_IN_CPYTHON
+#if CYTHON_COMPILING_IN_CPYTHON && (PY_VERSION_HEX >= 0x03020000 || PY_MAJOR_VERSION < 3 && PY_VERSION_HEX >= 0x02070000)
static CYTHON_INLINE PyObject* __Pyx_PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name) {
PyObject *res;
PyTypeObject *tp = Py_TYPE(obj);
@@ -762,7 +777,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_LookupSpecial(PyObject* obj, PyObj
return res;
}
#else
-#define __Pyx_PyObject_LookupSpecial(o,n) PyObject_GetAttr(o,n)
+#define __Pyx_PyObject_LookupSpecial(o,n) __Pyx_PyObject_GetAttrStr(o,n)
#endif
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
@@ -782,7 +797,6 @@ static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
((__pyx_CyFunctionObject *) (f))->defaults_getter = (g)
typedef struct {
PyCFunctionObject func;
- int flags;
PyObject *func_dict;
PyObject *func_weakreflist;
PyObject *func_name;
@@ -794,6 +808,7 @@ typedef struct {
PyObject *func_classobj; /* No-args super() class cell */
void *defaults;
int defaults_pyobjects;
+ int flags;
PyObject *defaults_tuple; /* Const defaults tuple */
PyObject *defaults_kwdict; /* Const kwonly defaults dict */
PyObject *(*defaults_getter)(PyObject *);
@@ -904,8 +919,8 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
/* Module declarations from 'posix.unistd' */
/* Module declarations from 's3ql.deltadump' */
-static PyTypeObject *__pyx_ptype_4s3ql_9deltadump___pyx_scope_struct_1_load_table = 0;
static PyTypeObject *__pyx_ptype_4s3ql_9deltadump___pyx_scope_struct__dump_table = 0;
+static PyTypeObject *__pyx_ptype_4s3ql_9deltadump___pyx_scope_struct_1_load_table = 0;
static int __pyx_v_4s3ql_9deltadump__INTEGER;
static int __pyx_v_4s3ql_9deltadump__BLOB;
static int __pyx_v_4s3ql_9deltadump__TIME;
@@ -953,8 +968,8 @@ static PyObject *__pyx_lambda_funcdef_lambda14(PyObject *__pyx_self); /* proto *
static PyObject *__pyx_lambda_funcdef_lambda15(PyObject *__pyx_self); /* proto */
static PyObject *__pyx_lambda_funcdef_lambda16(PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_table, PyObject *__pyx_v_columns, PyObject *__pyx_v_db, PyObject *__pyx_v_fh, PyObject *__pyx_v_trx_rows); /* proto */
-static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct_1_load_table(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct__dump_table(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct_1_load_table(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
static char __pyx_k_i[] = "i";
static char __pyx_k_j[] = "j";
static char __pyx_k__4[] = ", ";
@@ -1053,10 +1068,10 @@ static char __pyx_k_SELECT_s_FROM_s_ORDER_BY_s[] = "SELECT %s FROM %s ORDER BY %
static char __pyx_k_dump_table_s_writing_d_rows[] = "dump_table(%s): writing %d rows";
static char __pyx_k_load_table_s_reading_d_rows[] = "load_table(%s): reading %d rows";
static char __pyx_k_BLOB_too_large_to_read_d_vs_d[] = "BLOB too large to read (%d vs %d)";
-static char __pyx_k_home_nikratio_in_progress_s3ql[] = "/home/nikratio/in-progress/s3ql/src/s3ql/deltadump.pyx";
static char __pyx_k_Can_not_dump_BLOB_of_size_d_max[] = "Can not dump BLOB of size %d (max: %d)";
static char __pyx_k_SQLite_version_mismatch_between[] = "SQLite version mismatch between APSW and S3QL (%s vs %s)";
static char __pyx_k_deltadump_pyx_this_file_is_part[] = "\ndeltadump.pyx - this file is part of S3QL (http://s3ql.googlecode.com)\n\nCopyright (C) Nikolaus Rath <Nikolaus@rath.org>\n\nThis program can be distributed under the terms of the GNU GPLv3.\n";
+static char __pyx_k_home_nikratio_tmp_s3ql_src_s3ql[] = "/home/nikratio/tmp/s3ql/src/s3ql/deltadump.pyx";
static char __pyx_k_Can_t_access_in_memory_databases[] = "Can't access in-memory databases";
static char __pyx_k_SQLite_code_used_by_APSW_was_com[] = "SQLite code used by APSW was compiled with different options than SQLite code available to S3QL! Differing settings: + %s, - %s";
static char __pyx_k_apsw_sqlite_compile_options_s_s3[] = "apsw sqlite compile options: %s, s3ql sqlite compile options: %s";
@@ -1126,7 +1141,7 @@ static PyObject *__pyx_n_s_fp;
static PyObject *__pyx_n_s_getLogger;
static PyObject *__pyx_n_s_get_val;
static PyObject *__pyx_n_s_getfilesystemencoding;
-static PyObject *__pyx_kp_s_home_nikratio_in_progress_s3ql;
+static PyObject *__pyx_kp_s_home_nikratio_tmp_s3ql_src_s3ql;
static PyObject *__pyx_n_s_i;
static PyObject *__pyx_n_s_idx;
static PyObject *__pyx_n_s_import;
@@ -1415,7 +1430,7 @@ static int __pyx_f_4s3ql_9deltadump_raise_from_errno(struct __pyx_opt_args_4s3ql
__Pyx_GIVEREF(__pyx_t_2);
__pyx_t_1 = 0;
__pyx_t_2 = 0;
- __pyx_t_2 = PyObject_Call(__pyx_v_err_class, __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyObject_Call(__pyx_v_err_class, __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_Raise(__pyx_t_2, 0, 0, 0);
@@ -1711,7 +1726,7 @@ static int __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(int __pyx_v_rc, int __pyx_v_
PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
__Pyx_GIVEREF(__pyx_t_2);
__pyx_t_2 = 0;
- __pyx_t_2 = PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -1732,7 +1747,7 @@ static int __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(int __pyx_v_rc, int __pyx_v_
PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
__Pyx_GIVEREF(__pyx_t_2);
__pyx_t_2 = 0;
- __pyx_t_2 = PyObject_Call(((PyObject *)Py_TYPE(__pyx_v_exc)), __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)Py_TYPE(__pyx_v_exc)), __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_Raise(__pyx_t_2, 0, 0, 0);
@@ -1803,58 +1818,58 @@ static int __pyx_f_4s3ql_9deltadump_prep_columns(PyObject *__pyx_v_columns, int
int __pyx_clineno = 0;
__Pyx_RefNannySetupContext("prep_columns", 0);
- /* "s3ql/deltadump.pyx":198
- * cdef int col_count, *col_types, *col_args
+ /* "s3ql/deltadump.pyx":200
+ * cdef int *col_args
*
* col_count = len(columns) # <<<<<<<<<<<<<<
* col_types = < int *> calloc(col_count, sizeof(int))
* col_args = < int *> calloc(col_count, sizeof(int))
*/
- __pyx_t_1 = PyObject_Length(__pyx_v_columns); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyObject_Length(__pyx_v_columns); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__pyx_v_col_count = __pyx_t_1;
- /* "s3ql/deltadump.pyx":199
+ /* "s3ql/deltadump.pyx":201
*
* col_count = len(columns)
* col_types = < int *> calloc(col_count, sizeof(int)) # <<<<<<<<<<<<<<
* col_args = < int *> calloc(col_count, sizeof(int))
*
*/
- __pyx_t_2 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_v_col_count, (sizeof(int))); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_v_col_count, (sizeof(int))); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__pyx_v_col_types = ((int *)__pyx_t_2);
- /* "s3ql/deltadump.pyx":200
+ /* "s3ql/deltadump.pyx":202
* col_count = len(columns)
* col_types = < int *> calloc(col_count, sizeof(int))
* col_args = < int *> calloc(col_count, sizeof(int)) # <<<<<<<<<<<<<<
*
* # Initialize col_args and col_types
*/
- __pyx_t_2 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_v_col_count, (sizeof(int))); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_v_col_count, (sizeof(int))); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__pyx_v_col_args = ((int *)__pyx_t_2);
- /* "s3ql/deltadump.pyx":203
+ /* "s3ql/deltadump.pyx":205
*
* # Initialize col_args and col_types
* for i in range(col_count): # <<<<<<<<<<<<<<
* if columns[i][1] not in (BLOB, INTEGER, TIME):
* raise ValueError("Invalid type for column %d" % i)
*/
- __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_col_count); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_col_count); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_4);
PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_builtin_range, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_range, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
if (PyList_CheckExact(__pyx_t_3) || PyTuple_CheckExact(__pyx_t_3)) {
__pyx_t_4 = __pyx_t_3; __Pyx_INCREF(__pyx_t_4); __pyx_t_1 = 0;
__pyx_t_5 = NULL;
} else {
- __pyx_t_1 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_4);
__pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext;
}
@@ -1863,16 +1878,16 @@ static int __pyx_f_4s3ql_9deltadump_prep_columns(PyObject *__pyx_v_columns, int
if (!__pyx_t_5 && PyList_CheckExact(__pyx_t_4)) {
if (__pyx_t_1 >= PyList_GET_SIZE(__pyx_t_4)) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_3 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_3); __pyx_t_1++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_3); __pyx_t_1++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
#else
- __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
#endif
} else if (!__pyx_t_5 && PyTuple_CheckExact(__pyx_t_4)) {
if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_3); __pyx_t_1++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_3); __pyx_t_1++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
#else
- __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
#endif
} else {
__pyx_t_3 = __pyx_t_5(__pyx_t_4);
@@ -1880,7 +1895,7 @@ static int __pyx_f_4s3ql_9deltadump_prep_columns(PyObject *__pyx_v_columns, int
PyObject* exc_type = PyErr_Occurred();
if (exc_type) {
if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
- else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
break;
}
@@ -1889,43 +1904,43 @@ static int __pyx_f_4s3ql_9deltadump_prep_columns(PyObject *__pyx_v_columns, int
__Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_3);
__pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":204
+ /* "s3ql/deltadump.pyx":206
* # Initialize col_args and col_types
* for i in range(col_count):
* if columns[i][1] not in (BLOB, INTEGER, TIME): # <<<<<<<<<<<<<<
* raise ValueError("Invalid type for column %d" % i)
* col_types[i] = columns[i][1]
*/
- __pyx_t_3 = PyObject_GetItem(__pyx_v_columns, __pyx_v_i); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+ __pyx_t_3 = PyObject_GetItem(__pyx_v_columns, __pyx_v_i); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_3, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+ __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_3, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
__Pyx_GOTREF(__pyx_t_6);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_BLOB); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_BLOB); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_7 = PyObject_RichCompare(__pyx_t_6, __pyx_t_3, Py_NE); __Pyx_XGOTREF(__pyx_t_7); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_7 = PyObject_RichCompare(__pyx_t_6, __pyx_t_3, Py_NE); __Pyx_XGOTREF(__pyx_t_7); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
- if (((int)__pyx_t_8)) {
- __pyx_t_7 = __Pyx_GetModuleGlobalName(__pyx_n_s_INTEGER); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ if (__pyx_t_8) {
+ __pyx_t_7 = __Pyx_GetModuleGlobalName(__pyx_n_s_INTEGER); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_7);
- __pyx_t_3 = PyObject_RichCompare(__pyx_t_6, __pyx_t_7, Py_NE); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = PyObject_RichCompare(__pyx_t_6, __pyx_t_7, Py_NE); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
- __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely((__pyx_t_9 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_10 = ((int)__pyx_t_9);
+ __pyx_t_10 = __pyx_t_9;
} else {
- __pyx_t_10 = ((int)__pyx_t_8);
+ __pyx_t_10 = __pyx_t_8;
}
if (__pyx_t_10) {
- __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_TIME); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_TIME); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_7 = PyObject_RichCompare(__pyx_t_6, __pyx_t_3, Py_NE); __Pyx_XGOTREF(__pyx_t_7); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_7 = PyObject_RichCompare(__pyx_t_6, __pyx_t_3, Py_NE); __Pyx_XGOTREF(__pyx_t_7); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_8 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
- __pyx_t_9 = ((int)__pyx_t_8);
+ __pyx_t_9 = __pyx_t_8;
} else {
__pyx_t_9 = __pyx_t_10;
}
@@ -1933,94 +1948,94 @@ static int __pyx_f_4s3ql_9deltadump_prep_columns(PyObject *__pyx_v_columns, int
__pyx_t_10 = (__pyx_t_9 != 0);
if (__pyx_t_10) {
- /* "s3ql/deltadump.pyx":205
+ /* "s3ql/deltadump.pyx":207
* for i in range(col_count):
* if columns[i][1] not in (BLOB, INTEGER, TIME):
* raise ValueError("Invalid type for column %d" % i) # <<<<<<<<<<<<<<
* col_types[i] = columns[i][1]
*
*/
- __pyx_t_6 = PyUnicode_Format(__pyx_kp_u_Invalid_type_for_column_d, __pyx_v_i); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_6 = PyUnicode_Format(__pyx_kp_u_Invalid_type_for_column_d, __pyx_v_i); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_6);
- __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_7);
PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_6);
__Pyx_GIVEREF(__pyx_t_6);
__pyx_t_6 = 0;
- __pyx_t_6 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_7, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_6 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_t_7, NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_6);
__Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
__Pyx_Raise(__pyx_t_6, 0, 0, 0);
__Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
- /* "s3ql/deltadump.pyx":206
+ /* "s3ql/deltadump.pyx":208
* if columns[i][1] not in (BLOB, INTEGER, TIME):
* raise ValueError("Invalid type for column %d" % i)
* col_types[i] = columns[i][1] # <<<<<<<<<<<<<<
*
* if len(columns[i]) == 3:
*/
- __pyx_t_6 = PyObject_GetItem(__pyx_v_columns, __pyx_v_i); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+ __pyx_t_6 = PyObject_GetItem(__pyx_v_columns, __pyx_v_i); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
__Pyx_GOTREF(__pyx_t_6);
- __pyx_t_7 = __Pyx_GetItemInt(__pyx_t_6, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+ __pyx_t_7 = __Pyx_GetItemInt(__pyx_t_6, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
__Pyx_GOTREF(__pyx_t_7);
__Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
- __pyx_t_11 = __Pyx_PyInt_As_int(__pyx_t_7); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_11 = __Pyx_PyInt_As_int(__pyx_t_7); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
- __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
(__pyx_v_col_types[__pyx_t_12]) = __pyx_t_11;
- /* "s3ql/deltadump.pyx":208
+ /* "s3ql/deltadump.pyx":210
* col_types[i] = columns[i][1]
*
* if len(columns[i]) == 3: # <<<<<<<<<<<<<<
* col_args[i] = columns[i][2]
* else:
*/
- __pyx_t_7 = PyObject_GetItem(__pyx_v_columns, __pyx_v_i); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+ __pyx_t_7 = PyObject_GetItem(__pyx_v_columns, __pyx_v_i); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
__Pyx_GOTREF(__pyx_t_7);
- __pyx_t_12 = PyObject_Length(__pyx_t_7); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_12 = PyObject_Length(__pyx_t_7); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
__pyx_t_10 = ((__pyx_t_12 == 3) != 0);
if (__pyx_t_10) {
- /* "s3ql/deltadump.pyx":209
+ /* "s3ql/deltadump.pyx":211
*
* if len(columns[i]) == 3:
* col_args[i] = columns[i][2] # <<<<<<<<<<<<<<
* else:
* col_args[i] = 0
*/
- __pyx_t_7 = PyObject_GetItem(__pyx_v_columns, __pyx_v_i); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+ __pyx_t_7 = PyObject_GetItem(__pyx_v_columns, __pyx_v_i); if (unlikely(__pyx_t_7 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
__Pyx_GOTREF(__pyx_t_7);
- __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_7, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+ __pyx_t_6 = __Pyx_GetItemInt(__pyx_t_7, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_6 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
__Pyx_GOTREF(__pyx_t_6);
__Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
- __pyx_t_11 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_11 = __Pyx_PyInt_As_int(__pyx_t_6); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
- __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
(__pyx_v_col_args[__pyx_t_12]) = __pyx_t_11;
goto __pyx_L6;
}
/*else*/ {
- /* "s3ql/deltadump.pyx":211
+ /* "s3ql/deltadump.pyx":213
* col_args[i] = columns[i][2]
* else:
* col_args[i] = 0 # <<<<<<<<<<<<<<
*
* col_types_p[0] = col_types
*/
- __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
(__pyx_v_col_args[__pyx_t_12]) = 0;
}
__pyx_L6:;
}
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
- /* "s3ql/deltadump.pyx":213
+ /* "s3ql/deltadump.pyx":215
* col_args[i] = 0
*
* col_types_p[0] = col_types # <<<<<<<<<<<<<<
@@ -2029,7 +2044,7 @@ static int __pyx_f_4s3ql_9deltadump_prep_columns(PyObject *__pyx_v_columns, int
*/
(__pyx_v_col_types_p[0]) = __pyx_v_col_types;
- /* "s3ql/deltadump.pyx":214
+ /* "s3ql/deltadump.pyx":216
*
* col_types_p[0] = col_types
* col_args_p[0] = col_args # <<<<<<<<<<<<<<
@@ -2038,7 +2053,7 @@ static int __pyx_f_4s3ql_9deltadump_prep_columns(PyObject *__pyx_v_columns, int
*/
(__pyx_v_col_args_p[0]) = __pyx_v_col_args;
- /* "s3ql/deltadump.pyx":215
+ /* "s3ql/deltadump.pyx":217
* col_types_p[0] = col_types
* col_args_p[0] = col_args
* return col_count # <<<<<<<<<<<<<<
@@ -2070,7 +2085,7 @@ static int __pyx_f_4s3ql_9deltadump_prep_columns(PyObject *__pyx_v_columns, int
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":217
+/* "s3ql/deltadump.pyx":219
* return col_count
*
* cdef FILE* dup_to_fp(fh, const_char* mode) except NULL: # <<<<<<<<<<<<<<
@@ -2092,23 +2107,23 @@ static FILE *__pyx_f_4s3ql_9deltadump_dup_to_fp(PyObject *__pyx_v_fh, const char
int __pyx_clineno = 0;
__Pyx_RefNannySetupContext("dup_to_fp", 0);
- /* "s3ql/deltadump.pyx":222
+ /* "s3ql/deltadump.pyx":224
* cdef int fd
*
* fd = dup(fh.fileno()) # <<<<<<<<<<<<<<
* if fd == -1:
* raise_from_errno()
*/
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_fh, __pyx_n_s_fileno); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_fh, __pyx_n_s_fileno); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_2 = PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
__pyx_v_fd = dup(__pyx_t_3);
- /* "s3ql/deltadump.pyx":223
+ /* "s3ql/deltadump.pyx":225
*
* fd = dup(fh.fileno())
* if fd == -1: # <<<<<<<<<<<<<<
@@ -2118,19 +2133,19 @@ static FILE *__pyx_f_4s3ql_9deltadump_dup_to_fp(PyObject *__pyx_v_fh, const char
__pyx_t_4 = ((__pyx_v_fd == -1) != 0);
if (__pyx_t_4) {
- /* "s3ql/deltadump.pyx":224
+ /* "s3ql/deltadump.pyx":226
* fd = dup(fh.fileno())
* if fd == -1:
* raise_from_errno() # <<<<<<<<<<<<<<
*
* fp = fdopen(fd, mode)
*/
- __pyx_t_3 = __pyx_f_4s3ql_9deltadump_raise_from_errno(NULL); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __pyx_f_4s3ql_9deltadump_raise_from_errno(NULL); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 226; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
goto __pyx_L3;
}
__pyx_L3:;
- /* "s3ql/deltadump.pyx":226
+ /* "s3ql/deltadump.pyx":228
* raise_from_errno()
*
* fp = fdopen(fd, mode) # <<<<<<<<<<<<<<
@@ -2139,7 +2154,7 @@ static FILE *__pyx_f_4s3ql_9deltadump_dup_to_fp(PyObject *__pyx_v_fh, const char
*/
__pyx_v_fp = fdopen(__pyx_v_fd, __pyx_v_mode);
- /* "s3ql/deltadump.pyx":227
+ /* "s3ql/deltadump.pyx":229
*
* fp = fdopen(fd, mode)
* if fp == NULL: # <<<<<<<<<<<<<<
@@ -2149,19 +2164,19 @@ static FILE *__pyx_f_4s3ql_9deltadump_dup_to_fp(PyObject *__pyx_v_fh, const char
__pyx_t_4 = ((__pyx_v_fp == NULL) != 0);
if (__pyx_t_4) {
- /* "s3ql/deltadump.pyx":228
+ /* "s3ql/deltadump.pyx":230
* fp = fdopen(fd, mode)
* if fp == NULL:
* raise_from_errno() # <<<<<<<<<<<<<<
*
* return fp
*/
- __pyx_t_3 = __pyx_f_4s3ql_9deltadump_raise_from_errno(NULL); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 228; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __pyx_f_4s3ql_9deltadump_raise_from_errno(NULL); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 230; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
goto __pyx_L4;
}
__pyx_L4:;
- /* "s3ql/deltadump.pyx":230
+ /* "s3ql/deltadump.pyx":232
* raise_from_errno()
*
* return fp # <<<<<<<<<<<<<<
@@ -2171,7 +2186,7 @@ static FILE *__pyx_f_4s3ql_9deltadump_dup_to_fp(PyObject *__pyx_v_fh, const char
__pyx_r = __pyx_v_fp;
goto __pyx_L0;
- /* "s3ql/deltadump.pyx":217
+ /* "s3ql/deltadump.pyx":219
* return col_count
*
* cdef FILE* dup_to_fp(fh, const_char* mode) except NULL: # <<<<<<<<<<<<<<
@@ -2190,7 +2205,7 @@ static FILE *__pyx_f_4s3ql_9deltadump_dup_to_fp(PyObject *__pyx_v_fh, const char
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":232
+/* "s3ql/deltadump.pyx":234
* return fp
*
* def check_sqlite(): # <<<<<<<<<<<<<<
@@ -2235,57 +2250,57 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_check_sqlite(CYTHON_UNUSED PyObject *
int __pyx_clineno = 0;
__Pyx_RefNannySetupContext("check_sqlite", 0);
- /* "s3ql/deltadump.pyx":246
+ /* "s3ql/deltadump.pyx":248
* cdef const_char *buf
*
* apsw_sqlite_version = apsw.sqlitelibversion() # <<<<<<<<<<<<<<
* s3ql_sqlite_version = PyUnicode_FromString(sqlite3_libversion())
* log.debug('apsw sqlite version: %s, '
*/
- __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_apsw); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_apsw); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_sqlitelibversion); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_sqlitelibversion); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- __pyx_t_1 = PyObject_Call(__pyx_t_2, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
__pyx_v_apsw_sqlite_version = __pyx_t_1;
__pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":247
+ /* "s3ql/deltadump.pyx":249
*
* apsw_sqlite_version = apsw.sqlitelibversion()
* s3ql_sqlite_version = PyUnicode_FromString(sqlite3_libversion()) # <<<<<<<<<<<<<<
* log.debug('apsw sqlite version: %s, '
* 's3ql sqlite version: %s',
*/
- __pyx_t_1 = PyUnicode_FromString(sqlite3_libversion()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyUnicode_FromString(sqlite3_libversion()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__pyx_v_s3ql_sqlite_version = __pyx_t_1;
__pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":248
+ /* "s3ql/deltadump.pyx":250
* apsw_sqlite_version = apsw.sqlitelibversion()
* s3ql_sqlite_version = PyUnicode_FromString(sqlite3_libversion())
* log.debug('apsw sqlite version: %s, ' # <<<<<<<<<<<<<<
* 's3ql sqlite version: %s',
* apsw_sqlite_version,
*/
- __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_debug); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_debug); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":251
+ /* "s3ql/deltadump.pyx":253
* 's3ql sqlite version: %s',
* apsw_sqlite_version,
* s3ql_sqlite_version) # <<<<<<<<<<<<<<
* if apsw_sqlite_version != s3ql_sqlite_version:
* raise RuntimeError('SQLite version mismatch between APSW and S3QL '
*/
- __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_INCREF(__pyx_kp_u_apsw_sqlite_version_s_s3ql_sqlit);
PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_kp_u_apsw_sqlite_version_s_s3ql_sqlit);
@@ -2297,39 +2312,39 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_check_sqlite(CYTHON_UNUSED PyObject *
PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_s3ql_sqlite_version);
__Pyx_GIVEREF(__pyx_v_s3ql_sqlite_version);
- /* "s3ql/deltadump.pyx":248
+ /* "s3ql/deltadump.pyx":250
* apsw_sqlite_version = apsw.sqlitelibversion()
* s3ql_sqlite_version = PyUnicode_FromString(sqlite3_libversion())
* log.debug('apsw sqlite version: %s, ' # <<<<<<<<<<<<<<
* 's3ql sqlite version: %s',
* apsw_sqlite_version,
*/
- __pyx_t_3 = PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":252
+ /* "s3ql/deltadump.pyx":254
* apsw_sqlite_version,
* s3ql_sqlite_version)
* if apsw_sqlite_version != s3ql_sqlite_version: # <<<<<<<<<<<<<<
* raise RuntimeError('SQLite version mismatch between APSW and S3QL '
* '(%s vs %s)' % (apsw_sqlite_version, s3ql_sqlite_version))
*/
- __pyx_t_3 = PyObject_RichCompare(__pyx_v_apsw_sqlite_version, __pyx_v_s3ql_sqlite_version, Py_NE); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = PyObject_RichCompare(__pyx_v_apsw_sqlite_version, __pyx_v_s3ql_sqlite_version, Py_NE); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
if (__pyx_t_4) {
- /* "s3ql/deltadump.pyx":254
+ /* "s3ql/deltadump.pyx":256
* if apsw_sqlite_version != s3ql_sqlite_version:
* raise RuntimeError('SQLite version mismatch between APSW and S3QL '
* '(%s vs %s)' % (apsw_sqlite_version, s3ql_sqlite_version)) # <<<<<<<<<<<<<<
*
* apsw_sqlite_options = set(apsw.compile_options)
*/
- __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_INCREF(__pyx_v_apsw_sqlite_version);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_apsw_sqlite_version);
@@ -2337,130 +2352,125 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_check_sqlite(CYTHON_UNUSED PyObject *
__Pyx_INCREF(__pyx_v_s3ql_sqlite_version);
PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_s3ql_sqlite_version);
__Pyx_GIVEREF(__pyx_v_s3ql_sqlite_version);
- __pyx_t_1 = PyUnicode_Format(__pyx_kp_u_SQLite_version_mismatch_between, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyUnicode_Format(__pyx_kp_u_SQLite_version_mismatch_between, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":253
+ /* "s3ql/deltadump.pyx":255
* s3ql_sqlite_version)
* if apsw_sqlite_version != s3ql_sqlite_version:
* raise RuntimeError('SQLite version mismatch between APSW and S3QL ' # <<<<<<<<<<<<<<
* '(%s vs %s)' % (apsw_sqlite_version, s3ql_sqlite_version))
*
*/
- __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 255; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
__Pyx_GIVEREF(__pyx_t_1);
__pyx_t_1 = 0;
- __pyx_t_1 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 255; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_Raise(__pyx_t_1, 0, 0, 0);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 255; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
- /* "s3ql/deltadump.pyx":256
+ /* "s3ql/deltadump.pyx":258
* '(%s vs %s)' % (apsw_sqlite_version, s3ql_sqlite_version))
*
* apsw_sqlite_options = set(apsw.compile_options) # <<<<<<<<<<<<<<
* s3ql_sqlite_options = set()
* for idx in itertools.count(0):
*/
- __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_apsw); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_apsw); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_compile_options); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_compile_options); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PySet_New(__pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);
- __Pyx_GIVEREF(__pyx_t_3);
- __pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)(&PySet_Type))), __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_3);
- __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- __pyx_v_apsw_sqlite_options = ((PyObject*)__pyx_t_3);
- __pyx_t_3 = 0;
+ __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+ __pyx_v_apsw_sqlite_options = ((PyObject*)__pyx_t_1);
+ __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":257
+ /* "s3ql/deltadump.pyx":259
*
* apsw_sqlite_options = set(apsw.compile_options)
* s3ql_sqlite_options = set() # <<<<<<<<<<<<<<
* for idx in itertools.count(0):
* buf = sqlite3_compileoption_get(idx)
*/
- __pyx_t_3 = PySet_New(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_3);
- __pyx_v_s3ql_sqlite_options = ((PyObject*)__pyx_t_3);
- __pyx_t_3 = 0;
+ __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_1);
+ __pyx_v_s3ql_sqlite_options = ((PyObject*)__pyx_t_1);
+ __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":258
+ /* "s3ql/deltadump.pyx":260
* apsw_sqlite_options = set(apsw.compile_options)
* s3ql_sqlite_options = set()
* for idx in itertools.count(0): # <<<<<<<<<<<<<<
* buf = sqlite3_compileoption_get(idx)
* if buf is NULL:
*/
- __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_itertools); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_count); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_itertools); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_count); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- if (PyList_CheckExact(__pyx_t_3) || PyTuple_CheckExact(__pyx_t_3)) {
- __pyx_t_1 = __pyx_t_3; __Pyx_INCREF(__pyx_t_1); __pyx_t_5 = 0;
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_1);
+ __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+ if (PyList_CheckExact(__pyx_t_1) || PyTuple_CheckExact(__pyx_t_1)) {
+ __pyx_t_3 = __pyx_t_1; __Pyx_INCREF(__pyx_t_3); __pyx_t_5 = 0;
__pyx_t_6 = NULL;
} else {
- __pyx_t_5 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_1);
- __pyx_t_6 = Py_TYPE(__pyx_t_1)->tp_iternext;
+ __pyx_t_5 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_3);
+ __pyx_t_6 = Py_TYPE(__pyx_t_3)->tp_iternext;
}
- __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+ __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
for (;;) {
- if (!__pyx_t_6 && PyList_CheckExact(__pyx_t_1)) {
- if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_1)) break;
+ if (!__pyx_t_6 && PyList_CheckExact(__pyx_t_3)) {
+ if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_3)) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_5); __Pyx_INCREF(__pyx_t_3); __pyx_t_5++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
#else
- __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
#endif
- } else if (!__pyx_t_6 && PyTuple_CheckExact(__pyx_t_1)) {
- if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
+ } else if (!__pyx_t_6 && PyTuple_CheckExact(__pyx_t_3)) {
+ if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_5); __Pyx_INCREF(__pyx_t_3); __pyx_t_5++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
#else
- __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
#endif
} else {
- __pyx_t_3 = __pyx_t_6(__pyx_t_1);
- if (unlikely(!__pyx_t_3)) {
+ __pyx_t_1 = __pyx_t_6(__pyx_t_3);
+ if (unlikely(!__pyx_t_1)) {
PyObject* exc_type = PyErr_Occurred();
if (exc_type) {
if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
- else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
break;
}
- __Pyx_GOTREF(__pyx_t_3);
+ __Pyx_GOTREF(__pyx_t_1);
}
- __Pyx_XDECREF_SET(__pyx_v_idx, __pyx_t_3);
- __pyx_t_3 = 0;
+ __Pyx_XDECREF_SET(__pyx_v_idx, __pyx_t_1);
+ __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":259
+ /* "s3ql/deltadump.pyx":261
* s3ql_sqlite_options = set()
* for idx in itertools.count(0):
* buf = sqlite3_compileoption_get(idx) # <<<<<<<<<<<<<<
* if buf is NULL:
* break
*/
- __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_v_idx); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_v_idx); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__pyx_v_buf = sqlite3_compileoption_get(__pyx_t_7);
- /* "s3ql/deltadump.pyx":260
+ /* "s3ql/deltadump.pyx":262
* for idx in itertools.count(0):
* buf = sqlite3_compileoption_get(idx)
* if buf is NULL: # <<<<<<<<<<<<<<
@@ -2470,7 +2480,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_check_sqlite(CYTHON_UNUSED PyObject *
__pyx_t_4 = ((__pyx_v_buf == NULL) != 0);
if (__pyx_t_4) {
- /* "s3ql/deltadump.pyx":261
+ /* "s3ql/deltadump.pyx":263
* buf = sqlite3_compileoption_get(idx)
* if buf is NULL:
* break # <<<<<<<<<<<<<<
@@ -2480,146 +2490,146 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_check_sqlite(CYTHON_UNUSED PyObject *
goto __pyx_L5_break;
}
- /* "s3ql/deltadump.pyx":262
+ /* "s3ql/deltadump.pyx":264
* if buf is NULL:
* break
* s3ql_sqlite_options.add(PyUnicode_FromString(buf)) # <<<<<<<<<<<<<<
*
* log.debug('apsw sqlite compile options: %s, '
*/
- __pyx_t_3 = PyUnicode_FromString(__pyx_v_buf); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_3);
- __pyx_t_8 = PySet_Add(__pyx_v_s3ql_sqlite_options, __pyx_t_3); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+ __pyx_t_1 = PyUnicode_FromString(__pyx_v_buf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_1);
+ __pyx_t_8 = PySet_Add(__pyx_v_s3ql_sqlite_options, __pyx_t_1); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
}
__pyx_L5_break:;
- __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+ __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":264
+ /* "s3ql/deltadump.pyx":266
* s3ql_sqlite_options.add(PyUnicode_FromString(buf))
*
* log.debug('apsw sqlite compile options: %s, ' # <<<<<<<<<<<<<<
* 's3ql sqlite compile options: %s',
* apsw_sqlite_options,
*/
- __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_1);
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_debug); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
- __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_debug); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_1);
+ __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":267
+ /* "s3ql/deltadump.pyx":269
* 's3ql sqlite compile options: %s',
* apsw_sqlite_options,
* s3ql_sqlite_options) # <<<<<<<<<<<<<<
* if apsw_sqlite_options != s3ql_sqlite_options:
* raise RuntimeError('SQLite code used by APSW was compiled with different '
*/
- __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_1);
+ __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_3);
__Pyx_INCREF(__pyx_kp_u_apsw_sqlite_compile_options_s_s3);
- PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_kp_u_apsw_sqlite_compile_options_s_s3);
+ PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_kp_u_apsw_sqlite_compile_options_s_s3);
__Pyx_GIVEREF(__pyx_kp_u_apsw_sqlite_compile_options_s_s3);
__Pyx_INCREF(__pyx_v_apsw_sqlite_options);
- PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_apsw_sqlite_options);
+ PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_apsw_sqlite_options);
__Pyx_GIVEREF(__pyx_v_apsw_sqlite_options);
__Pyx_INCREF(__pyx_v_s3ql_sqlite_options);
- PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_s3ql_sqlite_options);
+ PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_s3ql_sqlite_options);
__Pyx_GIVEREF(__pyx_v_s3ql_sqlite_options);
- /* "s3ql/deltadump.pyx":264
+ /* "s3ql/deltadump.pyx":266
* s3ql_sqlite_options.add(PyUnicode_FromString(buf))
*
* log.debug('apsw sqlite compile options: %s, ' # <<<<<<<<<<<<<<
* 's3ql sqlite compile options: %s',
* apsw_sqlite_options,
*/
- __pyx_t_2 = PyObject_Call(__pyx_t_3, __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
- __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+ __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
- /* "s3ql/deltadump.pyx":268
+ /* "s3ql/deltadump.pyx":270
* apsw_sqlite_options,
* s3ql_sqlite_options)
* if apsw_sqlite_options != s3ql_sqlite_options: # <<<<<<<<<<<<<<
* raise RuntimeError('SQLite code used by APSW was compiled with different '
* 'options than SQLite code available to S3QL! '
*/
- __pyx_t_2 = PyObject_RichCompare(__pyx_v_apsw_sqlite_options, __pyx_v_s3ql_sqlite_options, Py_NE); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = PyObject_RichCompare(__pyx_v_apsw_sqlite_options, __pyx_v_s3ql_sqlite_options, Py_NE); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
if (__pyx_t_4) {
- /* "s3ql/deltadump.pyx":272
+ /* "s3ql/deltadump.pyx":274
* 'options than SQLite code available to S3QL! '
* 'Differing settings: + %s, - %s' %
* (apsw_sqlite_options - s3ql_sqlite_options, # <<<<<<<<<<<<<<
* s3ql_sqlite_options - apsw_sqlite_options))
*
*/
- __pyx_t_2 = PyNumber_Subtract(__pyx_v_apsw_sqlite_options, __pyx_v_s3ql_sqlite_options); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = PyNumber_Subtract(__pyx_v_apsw_sqlite_options, __pyx_v_s3ql_sqlite_options); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 274; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
- /* "s3ql/deltadump.pyx":273
+ /* "s3ql/deltadump.pyx":275
* 'Differing settings: + %s, - %s' %
* (apsw_sqlite_options - s3ql_sqlite_options,
* s3ql_sqlite_options - apsw_sqlite_options)) # <<<<<<<<<<<<<<
*
* def dump_table(table, order, columns, db, fh):
*/
- __pyx_t_1 = PyNumber_Subtract(__pyx_v_s3ql_sqlite_options, __pyx_v_apsw_sqlite_options); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_1);
+ __pyx_t_3 = PyNumber_Subtract(__pyx_v_s3ql_sqlite_options, __pyx_v_apsw_sqlite_options); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_3);
- /* "s3ql/deltadump.pyx":272
+ /* "s3ql/deltadump.pyx":274
* 'options than SQLite code available to S3QL! '
* 'Differing settings: + %s, - %s' %
* (apsw_sqlite_options - s3ql_sqlite_options, # <<<<<<<<<<<<<<
* s3ql_sqlite_options - apsw_sqlite_options))
*
*/
- __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_3);
- PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
+ __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 274; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_1);
+ PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
__Pyx_GIVEREF(__pyx_t_2);
- PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
- __Pyx_GIVEREF(__pyx_t_1);
+ PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3);
+ __Pyx_GIVEREF(__pyx_t_3);
__pyx_t_2 = 0;
- __pyx_t_1 = 0;
+ __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":271
+ /* "s3ql/deltadump.pyx":273
* raise RuntimeError('SQLite code used by APSW was compiled with different '
* 'options than SQLite code available to S3QL! '
* 'Differing settings: + %s, - %s' % # <<<<<<<<<<<<<<
* (apsw_sqlite_options - s3ql_sqlite_options,
* s3ql_sqlite_options - apsw_sqlite_options))
*/
- __pyx_t_1 = PyUnicode_Format(__pyx_kp_u_SQLite_code_used_by_APSW_was_com, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_1);
- __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+ __pyx_t_3 = PyUnicode_Format(__pyx_kp_u_SQLite_code_used_by_APSW_was_com, __pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_3);
+ __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":269
+ /* "s3ql/deltadump.pyx":271
* s3ql_sqlite_options)
* if apsw_sqlite_options != s3ql_sqlite_options:
* raise RuntimeError('SQLite code used by APSW was compiled with different ' # <<<<<<<<<<<<<<
* 'options than SQLite code available to S3QL! '
* 'Differing settings: + %s, - %s' %
*/
- __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __Pyx_GOTREF(__pyx_t_3);
- PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
- __Pyx_GIVEREF(__pyx_t_1);
- __pyx_t_1 = 0;
- __pyx_t_1 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+ PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);
+ __Pyx_GIVEREF(__pyx_t_3);
+ __pyx_t_3 = 0;
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+ __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
- /* "s3ql/deltadump.pyx":232
+ /* "s3ql/deltadump.pyx":234
* return fp
*
* def check_sqlite(): # <<<<<<<<<<<<<<
@@ -2647,7 +2657,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_check_sqlite(CYTHON_UNUSED PyObject *
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":275
+/* "s3ql/deltadump.pyx":277
* s3ql_sqlite_options - apsw_sqlite_options))
*
* def dump_table(table, order, columns, db, fh): # <<<<<<<<<<<<<<
@@ -2657,7 +2667,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_check_sqlite(CYTHON_UNUSED PyObject *
/* Python wrapper */
static PyObject *__pyx_pw_4s3ql_9deltadump_3dump_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_4s3ql_9deltadump_2dump_table[] = "dump_table(table, order, columns, db, fh)\nDump *columns* of *table* into *fh*\n\n *order* specifies the order in which the rows are written and must be a\n string that can be inserted after the \"ORDER BY\" clause in an SQL SELECT\n statement.\n \n *db* is an `s3ql.Connection` instance for the database.\n \n *columns* must a list of 3-tuples, one for each column that should be\n stored. The first element of the tuple must contain the column name and the\n second element the type of data stored in the column (`INTEGER`, `TIME`\n or `BLOB`). Times will be converted to nanosecond integers.\n \n For integers and seconds, the third tuple element specifies the expected\n change of the values between rows. For blobs it can be either zero\n (indicating variable length columns) or an integer specifying the length of\n the column values in bytes.\n\n This function will open a separate connection to the database, so\n the *db* connection should not be in EXCLUSIVE locking mode.\n (Using a separate connection avoids the requirement on the *apsw*\n and *deltadump* modules be linked against against binary\n compatible SQLite libraries).\n ";
+static char __pyx_doc_4s3ql_9deltadump_2dump_table[] = "dump_table(table, order, columns, db, fh)\nDump *columns* of *table* into *fh*\n\n *order* specifies the order in which the rows are written and must be a\n string that can be inserted after the \"ORDER BY\" clause in an SQL SELECT\n statement.\n\n *db* is an `s3ql.Connection` instance for the database.\n\n *columns* must a list of 3-tuples, one for each column that should be\n stored. The first element of the tuple must contain the column name and the\n second element the type of data stored in the column (`INTEGER`, `TIME`\n or `BLOB`). Times will be converted to nanosecond integers.\n\n For integers and seconds, the third tuple element specifies the expected\n change of the values between rows. For blobs it can be either zero\n (indicating variable length columns) or an integer specifying the length of\n the column values in bytes.\n\n This function will open a separate connection to the database, so\n the *db* connection should not be in EXCLUSIVE locking mode.\n (Using a separate connection avoids the requirement on the *apsw*\n and *deltadump* modules be linked against against binary\n compatible SQLite libraries).\n ";
static PyMethodDef __pyx_mdef_4s3ql_9deltadump_3dump_table = {__Pyx_NAMESTR("dump_table"), (PyCFunction)__pyx_pw_4s3ql_9deltadump_3dump_table, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_4s3ql_9deltadump_2dump_table)};
static PyObject *__pyx_pw_4s3ql_9deltadump_3dump_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
PyObject *__pyx_v_table = 0;
@@ -2694,26 +2704,26 @@ static PyObject *__pyx_pw_4s3ql_9deltadump_3dump_table(PyObject *__pyx_self, PyO
case 1:
if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_order)) != 0)) kw_args--;
else {
- __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
case 2:
if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_columns)) != 0)) kw_args--;
else {
- __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
case 3:
if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_db)) != 0)) kw_args--;
else {
- __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
case 4:
if (likely((values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_fh)) != 0)) kw_args--;
else {
- __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
}
if (unlikely(kw_args > 0)) {
- if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "dump_table") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "dump_table") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
} else if (PyTuple_GET_SIZE(__pyx_args) != 5) {
goto __pyx_L5_argtuple_error;
@@ -2732,7 +2742,7 @@ static PyObject *__pyx_pw_4s3ql_9deltadump_3dump_table(PyObject *__pyx_self, PyO
}
goto __pyx_L4_argument_unpacking_done;
__pyx_L5_argtuple_error:;
- __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("dump_table", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
__pyx_L3_error:;
__Pyx_AddTraceback("s3ql.deltadump.dump_table", __pyx_clineno, __pyx_lineno, __pyx_filename);
__Pyx_RefNannyFinishContext();
@@ -2745,7 +2755,7 @@ static PyObject *__pyx_pw_4s3ql_9deltadump_3dump_table(PyObject *__pyx_self, PyO
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":319
+/* "s3ql/deltadump.pyx":324
* SQLITE_OPEN_READONLY, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db), # <<<<<<<<<<<<<<
@@ -2782,23 +2792,23 @@ static PyObject *__pyx_lambda_funcdef_lambda1(PyObject *__pyx_self) {
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- /* "s3ql/deltadump.pyx":320
+ /* "s3ql/deltadump.pyx":325
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db),
* SQLITE_OK, sqlite3_db)) # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_extended_result_codes(sqlite3_db, 1),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_close(__pyx_cur_scope->__pyx_v_sqlite3_db), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_close(__pyx_cur_scope->__pyx_v_sqlite3_db), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":319
+ /* "s3ql/deltadump.pyx":324
* SQLITE_OPEN_READONLY, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_extended_result_codes(sqlite3_db, 1),
*/
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -2815,7 +2825,7 @@ static PyObject *__pyx_lambda_funcdef_lambda1(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":326
+/* "s3ql/deltadump.pyx":331
* # Get FILE* for buffered reading from *fh*
* fp = dup_to_fp(fh, b'wb')
* cm.callback(lambda: fclose(fp)) # <<<<<<<<<<<<<<
@@ -2851,8 +2861,8 @@ static PyObject *__pyx_lambda_funcdef_lambda2(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_fclose(__pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_fclose(__pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -2869,7 +2879,7 @@ static PyObject *__pyx_lambda_funcdef_lambda2(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":330
+/* "s3ql/deltadump.pyx":335
* # Allocate col_args and col_types
* col_count = prep_columns(columns, &col_types, &col_args)
* cm.callback(lambda: free(col_args)) # <<<<<<<<<<<<<<
@@ -2904,7 +2914,7 @@ static PyObject *__pyx_lambda_funcdef_lambda3(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_col_args); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_col_args); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__pyx_r = __pyx_t_1;
__pyx_t_1 = 0;
@@ -2921,7 +2931,7 @@ static PyObject *__pyx_lambda_funcdef_lambda3(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":331
+/* "s3ql/deltadump.pyx":336
* col_count = prep_columns(columns, &col_types, &col_args)
* cm.callback(lambda: free(col_args))
* cm.callback(lambda: free(col_types)) # <<<<<<<<<<<<<<
@@ -2956,7 +2966,7 @@ static PyObject *__pyx_lambda_funcdef_lambda4(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_col_types); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_col_types); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 336; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__pyx_r = __pyx_t_1;
__pyx_t_1 = 0;
@@ -2973,7 +2983,7 @@ static PyObject *__pyx_lambda_funcdef_lambda4(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":335
+/* "s3ql/deltadump.pyx":340
* # Allocate int64_prev
* int64_prev = < int64_t *> calloc(len(columns), sizeof(int64_t))
* cm.callback(lambda: free(int64_prev)) # <<<<<<<<<<<<<<
@@ -3008,7 +3018,7 @@ static PyObject *__pyx_lambda_funcdef_lambda5(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_int64_prev); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_int64_prev); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__pyx_r = __pyx_t_1;
__pyx_t_1 = 0;
@@ -3025,7 +3035,7 @@ static PyObject *__pyx_lambda_funcdef_lambda5(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":343
+/* "s3ql/deltadump.pyx":348
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt), # <<<<<<<<<<<<<<
@@ -3062,23 +3072,23 @@ static PyObject *__pyx_lambda_funcdef_lambda6(PyObject *__pyx_self) {
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- /* "s3ql/deltadump.pyx":344
+ /* "s3ql/deltadump.pyx":349
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt),
* SQLITE_OK, sqlite3_db)) # <<<<<<<<<<<<<<
*
* row_count = db.get_val("SELECT COUNT(rowid) FROM %s" % table)
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":343
+ /* "s3ql/deltadump.pyx":348
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
*
*/
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -3095,7 +3105,7 @@ static PyObject *__pyx_lambda_funcdef_lambda6(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":275
+/* "s3ql/deltadump.pyx":277
* s3ql_sqlite_options - apsw_sqlite_options))
*
* def dump_table(table, order, columns, db, fh): # <<<<<<<<<<<<<<
@@ -3151,34 +3161,34 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
}
__Pyx_GOTREF(__pyx_cur_scope);
- /* "s3ql/deltadump.pyx":309
+ /* "s3ql/deltadump.pyx":314
* cdef int64_t row_count
*
* if db.file == ':memory:': # <<<<<<<<<<<<<<
* raise ValueError("Can't access in-memory databases")
*
*/
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_2 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_kp_u_memory, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_kp_u_memory, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":310
+ /* "s3ql/deltadump.pyx":315
*
* if db.file == ':memory:':
* raise ValueError("Can't access in-memory databases") # <<<<<<<<<<<<<<
*
* with ExitStack() as cm:
*/
- __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 310; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_Raise(__pyx_t_1, 0, 0, 0);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 310; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
- /* "s3ql/deltadump.pyx":312
+ /* "s3ql/deltadump.pyx":317
* raise ValueError("Can't access in-memory databases")
*
* with ExitStack() as cm: # <<<<<<<<<<<<<<
@@ -3186,16 +3196,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
* log.debug('Opening connection to %s', db.file)
*/
/*with:*/ {
- __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_ExitStack); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_ExitStack); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- __pyx_t_4 = __Pyx_PyObject_LookupSpecial(__pyx_t_3, __pyx_n_s_exit); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_4 = __Pyx_PyObject_LookupSpecial(__pyx_t_3, __pyx_n_s_exit); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_4);
- __pyx_t_1 = __Pyx_PyObject_LookupSpecial(__pyx_t_3, __pyx_n_s_enter); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+ __pyx_t_1 = __Pyx_PyObject_LookupSpecial(__pyx_t_3, __pyx_n_s_enter); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_5 = PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -3210,21 +3220,21 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_v_cm = __pyx_t_5;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":314
+ /* "s3ql/deltadump.pyx":319
* with ExitStack() as cm:
* # Get SQLite connection
* log.debug('Opening connection to %s', db.file) # <<<<<<<<<<<<<<
* dbfile_b = db.file.encode(sys.getfilesystemencoding(), 'surrogateescape')
* SQLITE_CHECK_RC(sqlite3_open_v2(dbfile_b, &sqlite3_db,
*/
- __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_debug); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_debug); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_INCREF(__pyx_kp_u_Opening_connection_to_s);
PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_kp_u_Opening_connection_to_s);
@@ -3232,33 +3242,33 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_3, __pyx_t_1, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_1, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":315
+ /* "s3ql/deltadump.pyx":320
* # Get SQLite connection
* log.debug('Opening connection to %s', db.file)
* dbfile_b = db.file.encode(sys.getfilesystemencoding(), 'surrogateescape') # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_open_v2(dbfile_b, &sqlite3_db,
* SQLITE_OPEN_READONLY, NULL),
*/
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_encode); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_encode); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_sys); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_sys); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_getfilesystemencoding); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_getfilesystemencoding); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_3, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
@@ -3266,182 +3276,182 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_n_u_surrogateescape);
__Pyx_GIVEREF(__pyx_n_u_surrogateescape);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__pyx_v_dbfile_b = __pyx_t_5;
__pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":316
+ /* "s3ql/deltadump.pyx":321
* log.debug('Opening connection to %s', db.file)
* dbfile_b = db.file.encode(sys.getfilesystemencoding(), 'surrogateescape')
* SQLITE_CHECK_RC(sqlite3_open_v2(dbfile_b, &sqlite3_db, # <<<<<<<<<<<<<<
* SQLITE_OPEN_READONLY, NULL),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_9 = __Pyx_PyObject_AsString(__pyx_v_dbfile_b); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 316; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_9 = __Pyx_PyObject_AsString(__pyx_v_dbfile_b); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":318
+ /* "s3ql/deltadump.pyx":323
* SQLITE_CHECK_RC(sqlite3_open_v2(dbfile_b, &sqlite3_db,
* SQLITE_OPEN_READONLY, NULL),
* SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db),
* SQLITE_OK, sqlite3_db))
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_open_v2(__pyx_t_9, (&__pyx_cur_scope->__pyx_v_sqlite3_db), SQLITE_OPEN_READONLY, NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 316; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_open_v2(__pyx_t_9, (&__pyx_cur_scope->__pyx_v_sqlite3_db), SQLITE_OPEN_READONLY, NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":319
+ /* "s3ql/deltadump.pyx":324
* SQLITE_OPEN_READONLY, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_extended_result_codes(sqlite3_db, 1),
*/
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_lambda1, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_lambda1, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":321
+ /* "s3ql/deltadump.pyx":326
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db),
* SQLITE_OK, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_extended_result_codes(sqlite3_db, 1), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
*
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_extended_result_codes(__pyx_cur_scope->__pyx_v_sqlite3_db, 1), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_extended_result_codes(__pyx_cur_scope->__pyx_v_sqlite3_db, 1), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":325
+ /* "s3ql/deltadump.pyx":330
*
* # Get FILE* for buffered reading from *fh*
* fp = dup_to_fp(fh, b'wb') # <<<<<<<<<<<<<<
* cm.callback(lambda: fclose(fp))
*
*/
- __pyx_t_11 = __pyx_f_4s3ql_9deltadump_dup_to_fp(__pyx_v_fh, __pyx_k_wb); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_11 = __pyx_f_4s3ql_9deltadump_dup_to_fp(__pyx_v_fh, __pyx_k_wb); if (unlikely(__pyx_t_11 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__pyx_cur_scope->__pyx_v_fp = __pyx_t_11;
- /* "s3ql/deltadump.pyx":326
+ /* "s3ql/deltadump.pyx":331
* # Get FILE* for buffered reading from *fh*
* fp = dup_to_fp(fh, b'wb')
* cm.callback(lambda: fclose(fp)) # <<<<<<<<<<<<<<
*
* # Allocate col_args and col_types
*/
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_1lambda2, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_1lambda2, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1);
__Pyx_GIVEREF(__pyx_t_1);
__pyx_t_1 = 0;
- __pyx_t_1 = PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":329
+ /* "s3ql/deltadump.pyx":334
*
* # Allocate col_args and col_types
* col_count = prep_columns(columns, &col_types, &col_args) # <<<<<<<<<<<<<<
* cm.callback(lambda: free(col_args))
* cm.callback(lambda: free(col_types))
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_prep_columns(__pyx_v_columns, (&__pyx_cur_scope->__pyx_v_col_types), (&__pyx_cur_scope->__pyx_v_col_args)); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_prep_columns(__pyx_v_columns, (&__pyx_cur_scope->__pyx_v_col_types), (&__pyx_cur_scope->__pyx_v_col_args)); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__pyx_v_col_count = __pyx_t_10;
- /* "s3ql/deltadump.pyx":330
+ /* "s3ql/deltadump.pyx":335
* # Allocate col_args and col_types
* col_count = prep_columns(columns, &col_types, &col_args)
* cm.callback(lambda: free(col_args)) # <<<<<<<<<<<<<<
* cm.callback(lambda: free(col_types))
*
*/
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_5 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_2lambda3, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_2lambda3, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":331
+ /* "s3ql/deltadump.pyx":336
* col_count = prep_columns(columns, &col_types, &col_args)
* cm.callback(lambda: free(col_args))
* cm.callback(lambda: free(col_types)) # <<<<<<<<<<<<<<
*
* # Allocate int64_prev
*/
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 336; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_3lambda4, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_3lambda4, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 336; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 336; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 336; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":334
+ /* "s3ql/deltadump.pyx":339
*
* # Allocate int64_prev
* int64_prev = < int64_t *> calloc(len(columns), sizeof(int64_t)) # <<<<<<<<<<<<<<
* cm.callback(lambda: free(int64_prev))
*
*/
- __pyx_t_12 = PyObject_Length(__pyx_v_columns); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- __pyx_t_13 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_t_12, (sizeof(int64_t))); if (unlikely(__pyx_t_13 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyObject_Length(__pyx_v_columns); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 339; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_13 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_t_12, (sizeof(int64_t))); if (unlikely(__pyx_t_13 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 339; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__pyx_cur_scope->__pyx_v_int64_prev = ((int64_t *)__pyx_t_13);
- /* "s3ql/deltadump.pyx":335
+ /* "s3ql/deltadump.pyx":340
* # Allocate int64_prev
* int64_prev = < int64_t *> calloc(len(columns), sizeof(int64_t))
* cm.callback(lambda: free(int64_prev)) # <<<<<<<<<<<<<<
*
* # Prepare statement
*/
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_4lambda5, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_4lambda5, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1);
__Pyx_GIVEREF(__pyx_t_1);
__pyx_t_1 = 0;
- __pyx_t_1 = PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 335; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":338
+ /* "s3ql/deltadump.pyx":343
*
* # Prepare statement
* col_names = [ x[0] for x in columns ] # <<<<<<<<<<<<<<
@@ -3450,13 +3460,13 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
{ /* enter inner scope */
PyObject *__pyx_7genexpr__pyx_v_x = NULL;
- __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
+ __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
__Pyx_GOTREF(__pyx_t_1);
if (PyList_CheckExact(__pyx_v_columns) || PyTuple_CheckExact(__pyx_v_columns)) {
__pyx_t_5 = __pyx_v_columns; __Pyx_INCREF(__pyx_t_5); __pyx_t_12 = 0;
__pyx_t_14 = NULL;
} else {
- __pyx_t_12 = -1; __pyx_t_5 = PyObject_GetIter(__pyx_v_columns); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
+ __pyx_t_12 = -1; __pyx_t_5 = PyObject_GetIter(__pyx_v_columns); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
__Pyx_GOTREF(__pyx_t_5);
__pyx_t_14 = Py_TYPE(__pyx_t_5)->tp_iternext;
}
@@ -3464,16 +3474,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
if (!__pyx_t_14 && PyList_CheckExact(__pyx_t_5)) {
if (__pyx_t_12 >= PyList_GET_SIZE(__pyx_t_5)) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_3 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_12); __Pyx_INCREF(__pyx_t_3); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
+ __pyx_t_3 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_12); __Pyx_INCREF(__pyx_t_3); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
#else
- __pyx_t_3 = PySequence_ITEM(__pyx_t_5, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
+ __pyx_t_3 = PySequence_ITEM(__pyx_t_5, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
#endif
} else if (!__pyx_t_14 && PyTuple_CheckExact(__pyx_t_5)) {
if (__pyx_t_12 >= PyTuple_GET_SIZE(__pyx_t_5)) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_12); __Pyx_INCREF(__pyx_t_3); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
+ __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_12); __Pyx_INCREF(__pyx_t_3); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
#else
- __pyx_t_3 = PySequence_ITEM(__pyx_t_5, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
+ __pyx_t_3 = PySequence_ITEM(__pyx_t_5, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
#endif
} else {
__pyx_t_3 = __pyx_t_14(__pyx_t_5);
@@ -3481,7 +3491,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
PyObject* exc_type = PyErr_Occurred();
if (exc_type) {
if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
- else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
+ else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
}
break;
}
@@ -3489,9 +3499,9 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
}
__Pyx_XDECREF_SET(__pyx_7genexpr__pyx_v_x, __pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = __Pyx_GetItemInt(__pyx_7genexpr__pyx_v_x, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;};
+ __pyx_t_3 = __Pyx_GetItemInt(__pyx_7genexpr__pyx_v_x, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;};
__Pyx_GOTREF(__pyx_t_3);
- if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_3))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
+ if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_3))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L19_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
}
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
@@ -3505,16 +3515,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_v_col_names = ((PyObject*)__pyx_t_1);
__pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":340
+ /* "s3ql/deltadump.pyx":345
* col_names = [ x[0] for x in columns ]
* query = ("SELECT %s FROM %s ORDER BY %s " %
* (', '.join(col_names), table, order)).encode('utf-8') # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_1 = PyUnicode_Join(__pyx_kp_u__4, __pyx_v_col_names); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyUnicode_Join(__pyx_kp_u__4, __pyx_v_col_names); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 345; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 345; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1);
__Pyx_GIVEREF(__pyx_t_1);
@@ -3526,109 +3536,109 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__Pyx_GIVEREF(__pyx_v_order);
__pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":339
+ /* "s3ql/deltadump.pyx":344
* # Prepare statement
* col_names = [ x[0] for x in columns ]
* query = ("SELECT %s FROM %s ORDER BY %s " % # <<<<<<<<<<<<<<
* (', '.join(col_names), table, order)).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
*/
- __pyx_t_1 = PyUnicode_Format(__pyx_kp_u_SELECT_s_FROM_s_ORDER_BY_s, __pyx_t_5); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 339; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyUnicode_Format(__pyx_kp_u_SELECT_s_FROM_s_ORDER_BY_s, __pyx_t_5); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":340
+ /* "s3ql/deltadump.pyx":345
* col_names = [ x[0] for x in columns ]
* query = ("SELECT %s FROM %s ORDER BY %s " %
* (', '.join(col_names), table, order)).encode('utf-8') # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_5 = PyUnicode_AsUTF8String(((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyUnicode_AsUTF8String(((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 345; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__pyx_v_query = __pyx_t_5;
__pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":341
+ /* "s3ql/deltadump.pyx":346
* query = ("SELECT %s FROM %s ORDER BY %s " %
* (', '.join(col_names), table, order)).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt),
*/
- __pyx_t_15 = __Pyx_PyObject_AsString(__pyx_v_query); if (unlikely((!__pyx_t_15) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_15 = __Pyx_PyObject_AsString(__pyx_v_query); if (unlikely((!__pyx_t_15) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":342
+ /* "s3ql/deltadump.pyx":347
* (', '.join(col_names), table, order)).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt),
* SQLITE_OK, sqlite3_db))
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_15, -1, (&__pyx_cur_scope->__pyx_v_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_15, -1, (&__pyx_cur_scope->__pyx_v_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":343
+ /* "s3ql/deltadump.pyx":348
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
*
*/
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_1 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_5lambda6, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10dump_table_5lambda6, 0, __pyx_n_s_dump_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
__Pyx_GIVEREF(__pyx_t_1);
__pyx_t_1 = 0;
- __pyx_t_1 = PyObject_Call(__pyx_t_5, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":346
+ /* "s3ql/deltadump.pyx":351
* SQLITE_OK, sqlite3_db))
*
* row_count = db.get_val("SELECT COUNT(rowid) FROM %s" % table) # <<<<<<<<<<<<<<
* log.debug('dump_table(%s): writing %d rows', table, row_count)
* write_integer(row_count, fp)
*/
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_get_val); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_get_val); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_3 = PyUnicode_Format(__pyx_kp_u_SELECT_COUNT_rowid_FROM_s, __pyx_v_table); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyUnicode_Format(__pyx_kp_u_SELECT_COUNT_rowid_FROM_s, __pyx_v_table); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_16 = __Pyx_PyInt_As_int64_t(__pyx_t_3); if (unlikely((__pyx_t_16 == (int64_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_16 = __Pyx_PyInt_As_int64_t(__pyx_t_3); if (unlikely((__pyx_t_16 == (int64_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__pyx_v_row_count = __pyx_t_16;
- /* "s3ql/deltadump.pyx":347
+ /* "s3ql/deltadump.pyx":352
*
* row_count = db.get_val("SELECT COUNT(rowid) FROM %s" % table)
* log.debug('dump_table(%s): writing %d rows', table, row_count) # <<<<<<<<<<<<<<
* write_integer(row_count, fp)
*
*/
- __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_debug); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_debug); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_row_count); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_row_count); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_INCREF(__pyx_kp_u_dump_table_s_writing_d_rows);
PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_kp_u_dump_table_s_writing_d_rows);
@@ -3639,22 +3649,22 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":348
+ /* "s3ql/deltadump.pyx":353
* row_count = db.get_val("SELECT COUNT(rowid) FROM %s" % table)
* log.debug('dump_table(%s): writing %d rows', table, row_count)
* write_integer(row_count, fp) # <<<<<<<<<<<<<<
*
* # Iterate through rows
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_write_integer(__pyx_v_row_count, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_write_integer(__pyx_v_row_count, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 353; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":351
+ /* "s3ql/deltadump.pyx":356
*
* # Iterate through rows
* while True: # <<<<<<<<<<<<<<
@@ -3663,7 +3673,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
while (1) {
- /* "s3ql/deltadump.pyx":352
+ /* "s3ql/deltadump.pyx":357
* # Iterate through rows
* while True:
* rc = sqlite3_step(stmt) # <<<<<<<<<<<<<<
@@ -3672,7 +3682,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_rc = sqlite3_step(__pyx_cur_scope->__pyx_v_stmt);
- /* "s3ql/deltadump.pyx":353
+ /* "s3ql/deltadump.pyx":358
* while True:
* rc = sqlite3_step(stmt)
* if rc == SQLITE_DONE: # <<<<<<<<<<<<<<
@@ -3682,7 +3692,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = ((__pyx_v_rc == SQLITE_DONE) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":354
+ /* "s3ql/deltadump.pyx":359
* rc = sqlite3_step(stmt)
* if rc == SQLITE_DONE:
* break # <<<<<<<<<<<<<<
@@ -3692,16 +3702,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
goto __pyx_L24_break;
}
- /* "s3ql/deltadump.pyx":355
+ /* "s3ql/deltadump.pyx":360
* if rc == SQLITE_DONE:
* break
* SQLITE_CHECK_RC(rc, SQLITE_ROW, sqlite3_db) # <<<<<<<<<<<<<<
*
* for i in range(col_count):
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(__pyx_v_rc, SQLITE_ROW, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 355; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(__pyx_v_rc, SQLITE_ROW, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 360; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":357
+ /* "s3ql/deltadump.pyx":362
* SQLITE_CHECK_RC(rc, SQLITE_ROW, sqlite3_db)
*
* for i in range(col_count): # <<<<<<<<<<<<<<
@@ -3712,7 +3722,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
for (__pyx_t_17 = 0; __pyx_t_17 < __pyx_t_10; __pyx_t_17+=1) {
__pyx_v_i = __pyx_t_17;
- /* "s3ql/deltadump.pyx":358
+ /* "s3ql/deltadump.pyx":363
*
* for i in range(col_count):
* if sqlite3_column_type(stmt, i) is SQLITE_NULL: # <<<<<<<<<<<<<<
@@ -3722,21 +3732,21 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = ((sqlite3_column_type(__pyx_cur_scope->__pyx_v_stmt, __pyx_v_i) == SQLITE_NULL) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":359
+ /* "s3ql/deltadump.pyx":364
* for i in range(col_count):
* if sqlite3_column_type(stmt, i) is SQLITE_NULL:
* raise ValueError("Can't dump NULL values") # <<<<<<<<<<<<<<
*
* if col_types[i] == _INTEGER:
*/
- __pyx_t_3 = PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_Raise(__pyx_t_3, 0, 0, 0);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
}
- /* "s3ql/deltadump.pyx":361
+ /* "s3ql/deltadump.pyx":366
* raise ValueError("Can't dump NULL values")
*
* if col_types[i] == _INTEGER: # <<<<<<<<<<<<<<
@@ -3746,7 +3756,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = (((__pyx_cur_scope->__pyx_v_col_types[__pyx_v_i]) == __pyx_v_4s3ql_9deltadump__INTEGER) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":362
+ /* "s3ql/deltadump.pyx":367
*
* if col_types[i] == _INTEGER:
* int64 = sqlite3_column_int64(stmt, i) # <<<<<<<<<<<<<<
@@ -3755,7 +3765,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_int64 = sqlite3_column_int64(__pyx_cur_scope->__pyx_v_stmt, __pyx_v_i);
- /* "s3ql/deltadump.pyx":363
+ /* "s3ql/deltadump.pyx":368
* if col_types[i] == _INTEGER:
* int64 = sqlite3_column_int64(stmt, i)
* tmp = int64 # <<<<<<<<<<<<<<
@@ -3764,7 +3774,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_tmp = __pyx_v_int64;
- /* "s3ql/deltadump.pyx":364
+ /* "s3ql/deltadump.pyx":369
* int64 = sqlite3_column_int64(stmt, i)
* tmp = int64
* int64 -= int64_prev[i] + col_args[i] # <<<<<<<<<<<<<<
@@ -3773,7 +3783,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_int64 = (__pyx_v_int64 - ((__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_i]) + (__pyx_cur_scope->__pyx_v_col_args[__pyx_v_i])));
- /* "s3ql/deltadump.pyx":365
+ /* "s3ql/deltadump.pyx":370
* tmp = int64
* int64 -= int64_prev[i] + col_args[i]
* int64_prev[i] = tmp # <<<<<<<<<<<<<<
@@ -3782,18 +3792,18 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
(__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_i]) = __pyx_v_tmp;
- /* "s3ql/deltadump.pyx":366
+ /* "s3ql/deltadump.pyx":371
* int64 -= int64_prev[i] + col_args[i]
* int64_prev[i] = tmp
* write_integer(int64, fp) # <<<<<<<<<<<<<<
*
* elif col_types[i] == _TIME:
*/
- __pyx_t_18 = __pyx_f_4s3ql_9deltadump_write_integer(__pyx_v_int64, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_18 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_18 = __pyx_f_4s3ql_9deltadump_write_integer(__pyx_v_int64, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_18 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L29;
}
- /* "s3ql/deltadump.pyx":368
+ /* "s3ql/deltadump.pyx":373
* write_integer(int64, fp)
*
* elif col_types[i] == _TIME: # <<<<<<<<<<<<<<
@@ -3803,7 +3813,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = (((__pyx_cur_scope->__pyx_v_col_types[__pyx_v_i]) == __pyx_v_4s3ql_9deltadump__TIME) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":369
+ /* "s3ql/deltadump.pyx":374
*
* elif col_types[i] == _TIME:
* int64 = < int64_t > (sqlite3_column_double(stmt, i) * time_scale) # <<<<<<<<<<<<<<
@@ -3812,7 +3822,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_int64 = ((int64_t)(sqlite3_column_double(__pyx_cur_scope->__pyx_v_stmt, __pyx_v_i) * __pyx_v_4s3ql_9deltadump_time_scale));
- /* "s3ql/deltadump.pyx":370
+ /* "s3ql/deltadump.pyx":375
* elif col_types[i] == _TIME:
* int64 = < int64_t > (sqlite3_column_double(stmt, i) * time_scale)
* tmp = int64 # <<<<<<<<<<<<<<
@@ -3821,7 +3831,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_tmp = __pyx_v_int64;
- /* "s3ql/deltadump.pyx":371
+ /* "s3ql/deltadump.pyx":376
* int64 = < int64_t > (sqlite3_column_double(stmt, i) * time_scale)
* tmp = int64
* int64 -= int64_prev[i] + col_args[i] # <<<<<<<<<<<<<<
@@ -3830,7 +3840,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_int64 = (__pyx_v_int64 - ((__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_i]) + (__pyx_cur_scope->__pyx_v_col_args[__pyx_v_i])));
- /* "s3ql/deltadump.pyx":372
+ /* "s3ql/deltadump.pyx":377
* tmp = int64
* int64 -= int64_prev[i] + col_args[i]
* int64_prev[i] = tmp # <<<<<<<<<<<<<<
@@ -3839,18 +3849,18 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
(__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_i]) = __pyx_v_tmp;
- /* "s3ql/deltadump.pyx":373
+ /* "s3ql/deltadump.pyx":378
* int64 -= int64_prev[i] + col_args[i]
* int64_prev[i] = tmp
* write_integer(int64, fp) # <<<<<<<<<<<<<<
*
* elif col_types[i] == _BLOB:
*/
- __pyx_t_18 = __pyx_f_4s3ql_9deltadump_write_integer(__pyx_v_int64, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_18 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 373; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_18 = __pyx_f_4s3ql_9deltadump_write_integer(__pyx_v_int64, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_18 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 378; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L29;
}
- /* "s3ql/deltadump.pyx":375
+ /* "s3ql/deltadump.pyx":380
* write_integer(int64, fp)
*
* elif col_types[i] == _BLOB: # <<<<<<<<<<<<<<
@@ -3860,7 +3870,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = (((__pyx_cur_scope->__pyx_v_col_types[__pyx_v_i]) == __pyx_v_4s3ql_9deltadump__BLOB) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":376
+ /* "s3ql/deltadump.pyx":381
*
* elif col_types[i] == _BLOB:
* buf = sqlite3_column_blob(stmt, i) # <<<<<<<<<<<<<<
@@ -3869,7 +3879,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_buf = sqlite3_column_blob(__pyx_cur_scope->__pyx_v_stmt, __pyx_v_i);
- /* "s3ql/deltadump.pyx":377
+ /* "s3ql/deltadump.pyx":382
* elif col_types[i] == _BLOB:
* buf = sqlite3_column_blob(stmt, i)
* len_ = sqlite3_column_bytes(stmt, i) # <<<<<<<<<<<<<<
@@ -3878,44 +3888,44 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_len_ = sqlite3_column_bytes(__pyx_cur_scope->__pyx_v_stmt, __pyx_v_i);
- /* "s3ql/deltadump.pyx":378
+ /* "s3ql/deltadump.pyx":383
* buf = sqlite3_column_blob(stmt, i)
* len_ = sqlite3_column_bytes(stmt, i)
* if len_ > MAX_BLOB_SIZE: # <<<<<<<<<<<<<<
* raise ValueError('Can not dump BLOB of size %d (max: %d)',
* len_, MAX_BLOB_SIZE)
*/
- __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 378; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 378; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_t_1, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 378; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_t_1, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 378; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":380
+ /* "s3ql/deltadump.pyx":385
* if len_ > MAX_BLOB_SIZE:
* raise ValueError('Can not dump BLOB of size %d (max: %d)',
* len_, MAX_BLOB_SIZE) # <<<<<<<<<<<<<<
* if col_args[i] == 0:
* write_integer(len_ - int64_prev[i], fp)
*/
- __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 380; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- /* "s3ql/deltadump.pyx":379
+ /* "s3ql/deltadump.pyx":384
* len_ = sqlite3_column_bytes(stmt, i)
* if len_ > MAX_BLOB_SIZE:
* raise ValueError('Can not dump BLOB of size %d (max: %d)', # <<<<<<<<<<<<<<
* len_, MAX_BLOB_SIZE)
* if col_args[i] == 0:
*/
- __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 379; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_INCREF(__pyx_kp_u_Can_not_dump_BLOB_of_size_d_max);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_kp_u_Can_not_dump_BLOB_of_size_d_max);
@@ -3926,15 +3936,15 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__Pyx_GIVEREF(__pyx_t_1);
__pyx_t_5 = 0;
__pyx_t_1 = 0;
- __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 379; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_Raise(__pyx_t_1, 0, 0, 0);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 379; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
}
- /* "s3ql/deltadump.pyx":381
+ /* "s3ql/deltadump.pyx":386
* raise ValueError('Can not dump BLOB of size %d (max: %d)',
* len_, MAX_BLOB_SIZE)
* if col_args[i] == 0: # <<<<<<<<<<<<<<
@@ -3944,16 +3954,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = (((__pyx_cur_scope->__pyx_v_col_args[__pyx_v_i]) == 0) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":382
+ /* "s3ql/deltadump.pyx":387
* len_, MAX_BLOB_SIZE)
* if col_args[i] == 0:
* write_integer(len_ - int64_prev[i], fp) # <<<<<<<<<<<<<<
* int64_prev[i] = len_
* elif len_ != col_args[i]:
*/
- __pyx_t_18 = __pyx_f_4s3ql_9deltadump_write_integer((__pyx_v_len_ - (__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_i])), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_18 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 382; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_18 = __pyx_f_4s3ql_9deltadump_write_integer((__pyx_v_len_ - (__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_i])), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_18 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":383
+ /* "s3ql/deltadump.pyx":388
* if col_args[i] == 0:
* write_integer(len_ - int64_prev[i], fp)
* int64_prev[i] = len_ # <<<<<<<<<<<<<<
@@ -3964,7 +3974,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
goto __pyx_L31;
}
- /* "s3ql/deltadump.pyx":384
+ /* "s3ql/deltadump.pyx":389
* write_integer(len_ - int64_prev[i], fp)
* int64_prev[i] = len_
* elif len_ != col_args[i]: # <<<<<<<<<<<<<<
@@ -3974,20 +3984,20 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = ((__pyx_v_len_ != (__pyx_cur_scope->__pyx_v_col_args[__pyx_v_i])) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":385
+ /* "s3ql/deltadump.pyx":390
* int64_prev[i] = len_
* elif len_ != col_args[i]:
* raise ValueError("Length %d != %d in column %d" % (len_, col_args[i], i)) # <<<<<<<<<<<<<<
*
* if len_ != 0:
*/
- __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_cur_scope->__pyx_v_col_args[__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_cur_scope->__pyx_v_col_args[__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_19 = PyTuple_New(3); if (unlikely(!__pyx_t_19)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_19 = PyTuple_New(3); if (unlikely(!__pyx_t_19)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_19);
PyTuple_SET_ITEM(__pyx_t_19, 0, __pyx_t_1);
__Pyx_GIVEREF(__pyx_t_1);
@@ -3998,24 +4008,24 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_1 = 0;
__pyx_t_3 = 0;
__pyx_t_5 = 0;
- __pyx_t_5 = PyUnicode_Format(__pyx_kp_u_Length_d_d_in_column_d, __pyx_t_19); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyUnicode_Format(__pyx_kp_u_Length_d_d_in_column_d, __pyx_t_19); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_19); __pyx_t_19 = 0;
- __pyx_t_19 = PyTuple_New(1); if (unlikely(!__pyx_t_19)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_19 = PyTuple_New(1); if (unlikely(!__pyx_t_19)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_19);
PyTuple_SET_ITEM(__pyx_t_19, 0, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_builtin_ValueError, __pyx_t_19, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_t_19, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_19); __pyx_t_19 = 0;
__Pyx_Raise(__pyx_t_5, 0, 0, 0);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
}
__pyx_L31:;
- /* "s3ql/deltadump.pyx":387
+ /* "s3ql/deltadump.pyx":392
* raise ValueError("Length %d != %d in column %d" % (len_, col_args[i], i))
*
* if len_ != 0: # <<<<<<<<<<<<<<
@@ -4025,14 +4035,14 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = ((__pyx_v_len_ != 0) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":388
+ /* "s3ql/deltadump.pyx":393
*
* if len_ != 0:
* fwrite(buf, len_, fp) # <<<<<<<<<<<<<<
*
* def load_table(table, columns, db, fh, trx_rows=5000):
*/
- __pyx_t_18 = __pyx_f_4s3ql_9deltadump_fwrite(__pyx_v_buf, __pyx_v_len_, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_18 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 388; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_18 = __pyx_f_4s3ql_9deltadump_fwrite(__pyx_v_buf, __pyx_v_len_, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_18 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L32;
}
__pyx_L32:;
@@ -4053,7 +4063,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__Pyx_XDECREF(__pyx_t_19); __pyx_t_19 = 0;
__Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":312
+ /* "s3ql/deltadump.pyx":317
* raise ValueError("Can't access in-memory databases")
*
* with ExitStack() as cm: # <<<<<<<<<<<<<<
@@ -4062,20 +4072,20 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
*/
/*except:*/ {
__Pyx_AddTraceback("s3ql.deltadump.dump_table", __pyx_clineno, __pyx_lineno, __pyx_filename);
- if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_19, &__pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_19, &__pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_GOTREF(__pyx_t_19);
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = PyTuple_Pack(3, __pyx_t_5, __pyx_t_19, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ __pyx_t_1 = PyTuple_Pack(3, __pyx_t_5, __pyx_t_19, __pyx_t_3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_20 = PyObject_Call(__pyx_t_4, __pyx_t_1, NULL);
+ __pyx_t_20 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_1, NULL);
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- if (unlikely(!__pyx_t_20)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ if (unlikely(!__pyx_t_20)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
__Pyx_GOTREF(__pyx_t_20);
__pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_20);
__Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
- if (__pyx_t_2 < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ if (__pyx_t_2 < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
__pyx_t_21 = ((!(__pyx_t_2 != 0)) != 0);
if (__pyx_t_21) {
__Pyx_GIVEREF(__pyx_t_5);
@@ -4083,7 +4093,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__Pyx_XGIVEREF(__pyx_t_3);
__Pyx_ErrRestore(__pyx_t_5, __pyx_t_19, __pyx_t_3);
__pyx_t_5 = 0; __pyx_t_19 = 0; __pyx_t_3 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
}
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_19); __pyx_t_19 = 0;
@@ -4107,9 +4117,9 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
/*finally:*/ {
/*normal exit:*/{
if (__pyx_t_4) {
- __pyx_t_8 = PyObject_Call(__pyx_t_4, __pyx_tuple__6, NULL);
+ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_tuple__6, NULL);
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
- if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_8);
__Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
}
@@ -4124,7 +4134,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
__pyx_L36:;
}
- /* "s3ql/deltadump.pyx":275
+ /* "s3ql/deltadump.pyx":277
* s3ql_sqlite_options - apsw_sqlite_options))
*
* def dump_table(table, order, columns, db, fh): # <<<<<<<<<<<<<<
@@ -4153,7 +4163,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":390
+/* "s3ql/deltadump.pyx":395
* fwrite(buf, len_, fp)
*
* def load_table(table, columns, db, fh, trx_rows=5000): # <<<<<<<<<<<<<<
@@ -4163,7 +4173,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_2dump_table(CYTHON_UNUSED PyObject *_
/* Python wrapper */
static PyObject *__pyx_pw_4s3ql_9deltadump_5load_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_4s3ql_9deltadump_4load_table[] = "load_table(table, columns, db, fh, trx_rows=5000)\nLoad *columns* of *table* from *fh*\n\n *db* is an `s3ql.Connection` instance for the database.\n \n *columns* must be the same list of 3-tuples that was passed to\n `dump_table` when creating the dump stored in *fh*.\n\n This function will open a separate connection to the database, so\n the *db* connection should not be in EXCLUSIVE locking mode.\n (Using a separate connection avoids the requirement on the *apsw*\n and *deltadump* modules be linked against against binary\n compatible SQLite libraries).\n\n When writing into the table, a new transaction will be started\n every *trx_rows* rows.\n ";
+static char __pyx_doc_4s3ql_9deltadump_4load_table[] = "load_table(table, columns, db, fh, trx_rows=5000)\nLoad *columns* of *table* from *fh*\n\n *db* is an `s3ql.Connection` instance for the database.\n\n *columns* must be the same list of 3-tuples that was passed to\n `dump_table` when creating the dump stored in *fh*.\n\n This function will open a separate connection to the database, so\n the *db* connection should not be in EXCLUSIVE locking mode.\n (Using a separate connection avoids the requirement on the *apsw*\n and *deltadump* modules be linked against against binary\n compatible SQLite libraries).\n\n When writing into the table, a new transaction will be started\n every *trx_rows* rows.\n ";
static PyMethodDef __pyx_mdef_4s3ql_9deltadump_5load_table = {__Pyx_NAMESTR("load_table"), (PyCFunction)__pyx_pw_4s3ql_9deltadump_5load_table, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_4s3ql_9deltadump_4load_table)};
static PyObject *__pyx_pw_4s3ql_9deltadump_5load_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
PyObject *__pyx_v_table = 0;
@@ -4201,17 +4211,17 @@ static PyObject *__pyx_pw_4s3ql_9deltadump_5load_table(PyObject *__pyx_self, PyO
case 1:
if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_columns)) != 0)) kw_args--;
else {
- __Pyx_RaiseArgtupleInvalid("load_table", 0, 4, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("load_table", 0, 4, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
case 2:
if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_db)) != 0)) kw_args--;
else {
- __Pyx_RaiseArgtupleInvalid("load_table", 0, 4, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("load_table", 0, 4, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
case 3:
if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_fh)) != 0)) kw_args--;
else {
- __Pyx_RaiseArgtupleInvalid("load_table", 0, 4, 5, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("load_table", 0, 4, 5, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
case 4:
if (kw_args > 0) {
@@ -4220,7 +4230,7 @@ static PyObject *__pyx_pw_4s3ql_9deltadump_5load_table(PyObject *__pyx_self, PyO
}
}
if (unlikely(kw_args > 0)) {
- if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "load_table") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "load_table") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
}
} else {
switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -4241,7 +4251,7 @@ static PyObject *__pyx_pw_4s3ql_9deltadump_5load_table(PyObject *__pyx_self, PyO
}
goto __pyx_L4_argument_unpacking_done;
__pyx_L5_argtuple_error:;
- __Pyx_RaiseArgtupleInvalid("load_table", 0, 4, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+ __Pyx_RaiseArgtupleInvalid("load_table", 0, 4, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
__pyx_L3_error:;
__Pyx_AddTraceback("s3ql.deltadump.load_table", __pyx_clineno, __pyx_lineno, __pyx_filename);
__Pyx_RefNannyFinishContext();
@@ -4254,7 +4264,7 @@ static PyObject *__pyx_pw_4s3ql_9deltadump_5load_table(PyObject *__pyx_self, PyO
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":426
+/* "s3ql/deltadump.pyx":435
* SQLITE_OPEN_READWRITE, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db), # <<<<<<<<<<<<<<
@@ -4291,23 +4301,23 @@ static PyObject *__pyx_lambda_funcdef_lambda7(PyObject *__pyx_self) {
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- /* "s3ql/deltadump.pyx":427
+ /* "s3ql/deltadump.pyx":436
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db),
* SQLITE_OK, sqlite3_db)) # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_extended_result_codes(sqlite3_db, 1),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_close(__pyx_cur_scope->__pyx_v_sqlite3_db), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_close(__pyx_cur_scope->__pyx_v_sqlite3_db), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":426
+ /* "s3ql/deltadump.pyx":435
* SQLITE_OPEN_READWRITE, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_extended_result_codes(sqlite3_db, 1),
*/
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -4324,7 +4334,7 @@ static PyObject *__pyx_lambda_funcdef_lambda7(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":447
+/* "s3ql/deltadump.pyx":456
* # Get FILE* for buffered reading from *fh*
* fp = dup_to_fp(fh, b'rb')
* cm.callback(lambda: fclose(fp)) # <<<<<<<<<<<<<<
@@ -4360,8 +4370,8 @@ static PyObject *__pyx_lambda_funcdef_lambda8(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_fclose(__pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_fclose(__pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -4378,7 +4388,7 @@ static PyObject *__pyx_lambda_funcdef_lambda8(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":451
+/* "s3ql/deltadump.pyx":460
* # Allocate col_args and col_types
* col_count = prep_columns(columns, &col_types, &col_args)
* cm.callback(lambda: free(col_args)) # <<<<<<<<<<<<<<
@@ -4413,7 +4423,7 @@ static PyObject *__pyx_lambda_funcdef_lambda9(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_col_args); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_col_args); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 460; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__pyx_r = __pyx_t_1;
__pyx_t_1 = 0;
@@ -4430,7 +4440,7 @@ static PyObject *__pyx_lambda_funcdef_lambda9(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":452
+/* "s3ql/deltadump.pyx":461
* col_count = prep_columns(columns, &col_types, &col_args)
* cm.callback(lambda: free(col_args))
* cm.callback(lambda: free(col_types)) # <<<<<<<<<<<<<<
@@ -4465,7 +4475,7 @@ static PyObject *__pyx_lambda_funcdef_lambda10(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_col_types); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_col_types); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__pyx_r = __pyx_t_1;
__pyx_t_1 = 0;
@@ -4482,7 +4492,7 @@ static PyObject *__pyx_lambda_funcdef_lambda10(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":456
+/* "s3ql/deltadump.pyx":465
* # Allocate int64_prev
* int64_prev = < int64_t *> calloc(len(columns), sizeof(int64_t))
* cm.callback(lambda: free(int64_prev)) # <<<<<<<<<<<<<<
@@ -4517,7 +4527,7 @@ static PyObject *__pyx_lambda_funcdef_lambda11(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_int64_prev); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_int64_prev); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__pyx_r = __pyx_t_1;
__pyx_t_1 = 0;
@@ -4534,7 +4544,7 @@ static PyObject *__pyx_lambda_funcdef_lambda11(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":465
+/* "s3ql/deltadump.pyx":474
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt), # <<<<<<<<<<<<<<
@@ -4571,23 +4581,23 @@ static PyObject *__pyx_lambda_funcdef_lambda12(PyObject *__pyx_self) {
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- /* "s3ql/deltadump.pyx":466
+ /* "s3ql/deltadump.pyx":475
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt),
* SQLITE_OK, sqlite3_db)) # <<<<<<<<<<<<<<
*
* # Prepare BEGIN statement
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":465
+ /* "s3ql/deltadump.pyx":474
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
*
*/
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -4604,7 +4614,7 @@ static PyObject *__pyx_lambda_funcdef_lambda12(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":472
+/* "s3ql/deltadump.pyx":481
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &begin_stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(begin_stmt), # <<<<<<<<<<<<<<
@@ -4641,23 +4651,23 @@ static PyObject *__pyx_lambda_funcdef_lambda13(PyObject *__pyx_self) {
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- /* "s3ql/deltadump.pyx":473
+ /* "s3ql/deltadump.pyx":482
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(begin_stmt),
* SQLITE_OK, sqlite3_db)) # <<<<<<<<<<<<<<
*
* # Prepare COMMIT statement
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 481; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":472
+ /* "s3ql/deltadump.pyx":481
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &begin_stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(begin_stmt), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
*
*/
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 481; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -4674,7 +4684,7 @@ static PyObject *__pyx_lambda_funcdef_lambda13(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":479
+/* "s3ql/deltadump.pyx":488
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &commit_stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(commit_stmt), # <<<<<<<<<<<<<<
@@ -4711,23 +4721,23 @@ static PyObject *__pyx_lambda_funcdef_lambda14(PyObject *__pyx_self) {
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- /* "s3ql/deltadump.pyx":480
+ /* "s3ql/deltadump.pyx":489
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(commit_stmt),
* SQLITE_OK, sqlite3_db)) # <<<<<<<<<<<<<<
*
* buf = calloc(MAX_BLOB_SIZE, 1)
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_commit_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_commit_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":479
+ /* "s3ql/deltadump.pyx":488
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &commit_stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(commit_stmt), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
*
*/
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -4744,7 +4754,7 @@ static PyObject *__pyx_lambda_funcdef_lambda14(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":483
+/* "s3ql/deltadump.pyx":492
*
* buf = calloc(MAX_BLOB_SIZE, 1)
* cm.callback(lambda: free(buf)) # <<<<<<<<<<<<<<
@@ -4779,7 +4789,7 @@ static PyObject *__pyx_lambda_funcdef_lambda15(PyObject *__pyx_self) {
__pyx_outer_scope = (struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *) __Pyx_CyFunction_GetClosure(__pyx_self);
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_buf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 483; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_free(__pyx_cur_scope->__pyx_v_buf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__pyx_r = __pyx_t_1;
__pyx_t_1 = 0;
@@ -4796,7 +4806,7 @@ static PyObject *__pyx_lambda_funcdef_lambda15(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":489
+/* "s3ql/deltadump.pyx":498
* # Start transaction
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_step(commit_stmt), # <<<<<<<<<<<<<<
@@ -4833,23 +4843,23 @@ static PyObject *__pyx_lambda_funcdef_lambda16(PyObject *__pyx_self) {
__pyx_cur_scope = __pyx_outer_scope;
__Pyx_XDECREF(__pyx_r);
- /* "s3ql/deltadump.pyx":490
+ /* "s3ql/deltadump.pyx":499
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_step(commit_stmt),
* SQLITE_DONE, sqlite3_db)) # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_reset(begin_stmt), SQLITE_OK, sqlite3_db)
*
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_commit_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_commit_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 498; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":489
+ /* "s3ql/deltadump.pyx":498
* # Start transaction
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_step(commit_stmt), # <<<<<<<<<<<<<<
* SQLITE_DONE, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_reset(begin_stmt), SQLITE_OK, sqlite3_db)
*/
- __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 498; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_2);
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
@@ -4866,7 +4876,7 @@ static PyObject *__pyx_lambda_funcdef_lambda16(PyObject *__pyx_self) {
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":390
+/* "s3ql/deltadump.pyx":395
* fwrite(buf, len_, fp)
*
* def load_table(table, columns, db, fh, trx_rows=5000): # <<<<<<<<<<<<<<
@@ -4932,34 +4942,34 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
}
__Pyx_GOTREF(__pyx_cur_scope);
- /* "s3ql/deltadump.pyx":416
+ /* "s3ql/deltadump.pyx":425
* cdef int64_t row_count, int64
*
* if db.file == ':memory:': # <<<<<<<<<<<<<<
* raise ValueError("Can't access in-memory databases")
*
*/
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 416; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 425; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_2 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_kp_u_memory, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 416; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_2 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_kp_u_memory, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 425; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":417
+ /* "s3ql/deltadump.pyx":426
*
* if db.file == ':memory:':
* raise ValueError("Can't access in-memory databases") # <<<<<<<<<<<<<<
*
* with ExitStack() as cm:
*/
- __pyx_t_1 = PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_Raise(__pyx_t_1, 0, 0, 0);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
- /* "s3ql/deltadump.pyx":419
+ /* "s3ql/deltadump.pyx":428
* raise ValueError("Can't access in-memory databases")
*
* with ExitStack() as cm: # <<<<<<<<<<<<<<
@@ -4967,16 +4977,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
* log.debug('Opening connection to %s', db.file)
*/
/*with:*/ {
- __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_ExitStack); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_ExitStack); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_3 = PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- __pyx_t_4 = __Pyx_PyObject_LookupSpecial(__pyx_t_3, __pyx_n_s_exit); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_4 = __Pyx_PyObject_LookupSpecial(__pyx_t_3, __pyx_n_s_exit); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_4);
- __pyx_t_1 = __Pyx_PyObject_LookupSpecial(__pyx_t_3, __pyx_n_s_enter); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+ __pyx_t_1 = __Pyx_PyObject_LookupSpecial(__pyx_t_3, __pyx_n_s_enter); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_5 = PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -4991,21 +5001,21 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_v_cm = __pyx_t_5;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":421
+ /* "s3ql/deltadump.pyx":430
* with ExitStack() as cm:
* # Get SQLite connection
* log.debug('Opening connection to %s', db.file) # <<<<<<<<<<<<<<
* dbfile_b = db.file.encode(sys.getfilesystemencoding(), 'surrogateescape')
* SQLITE_CHECK_RC(sqlite3_open_v2(dbfile_b, &sqlite3_db,
*/
- __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_debug); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_debug); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_INCREF(__pyx_kp_u_Opening_connection_to_s);
PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_kp_u_Opening_connection_to_s);
@@ -5013,33 +5023,33 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_3, __pyx_t_1, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_1, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":422
+ /* "s3ql/deltadump.pyx":431
* # Get SQLite connection
* log.debug('Opening connection to %s', db.file)
* dbfile_b = db.file.encode(sys.getfilesystemencoding(), 'surrogateescape') # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_open_v2(dbfile_b, &sqlite3_db,
* SQLITE_OPEN_READWRITE, NULL),
*/
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_file); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_encode); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_encode); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_sys); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_sys); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_getfilesystemencoding); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_getfilesystemencoding); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_3, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
@@ -5047,63 +5057,63 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_n_u_surrogateescape);
__Pyx_GIVEREF(__pyx_n_u_surrogateescape);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__pyx_v_dbfile_b = __pyx_t_5;
__pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":423
+ /* "s3ql/deltadump.pyx":432
* log.debug('Opening connection to %s', db.file)
* dbfile_b = db.file.encode(sys.getfilesystemencoding(), 'surrogateescape')
* SQLITE_CHECK_RC(sqlite3_open_v2(dbfile_b, &sqlite3_db, # <<<<<<<<<<<<<<
* SQLITE_OPEN_READWRITE, NULL),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_9 = __Pyx_PyObject_AsString(__pyx_v_dbfile_b); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_9 = __Pyx_PyObject_AsString(__pyx_v_dbfile_b); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 432; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":425
+ /* "s3ql/deltadump.pyx":434
* SQLITE_CHECK_RC(sqlite3_open_v2(dbfile_b, &sqlite3_db,
* SQLITE_OPEN_READWRITE, NULL),
* SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db),
* SQLITE_OK, sqlite3_db))
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_open_v2(__pyx_t_9, (&__pyx_cur_scope->__pyx_v_sqlite3_db), SQLITE_OPEN_READWRITE, NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_open_v2(__pyx_t_9, (&__pyx_cur_scope->__pyx_v_sqlite3_db), SQLITE_OPEN_READWRITE, NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 432; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":426
+ /* "s3ql/deltadump.pyx":435
* SQLITE_OPEN_READWRITE, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_extended_result_codes(sqlite3_db, 1),
*/
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_lambda7, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_lambda7, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":428
+ /* "s3ql/deltadump.pyx":437
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_close(sqlite3_db),
* SQLITE_OK, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_extended_result_codes(sqlite3_db, 1), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
*
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_extended_result_codes(__pyx_cur_scope->__pyx_v_sqlite3_db, 1), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_extended_result_codes(__pyx_cur_scope->__pyx_v_sqlite3_db, 1), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":432
+ /* "s3ql/deltadump.pyx":441
*
* # Copy settings
* for pragma in ('synchronous', 'foreign_keys'): # <<<<<<<<<<<<<<
@@ -5114,44 +5124,44 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
for (;;) {
if (__pyx_t_11 >= 2) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_11); __Pyx_INCREF(__pyx_t_1); __pyx_t_11++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 432; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_11); __Pyx_INCREF(__pyx_t_1); __pyx_t_11++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
#else
- __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_11); __pyx_t_11++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 432; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_11); __pyx_t_11++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
#endif
__Pyx_XDECREF_SET(__pyx_v_pragma, ((PyObject*)__pyx_t_1));
__pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":433
+ /* "s3ql/deltadump.pyx":442
* # Copy settings
* for pragma in ('synchronous', 'foreign_keys'):
* val = db.get_val('PRAGMA %s' % pragma) # <<<<<<<<<<<<<<
* cmd = ('PRAGMA %s = %s' % (pragma, val)).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, cmd, -1, &stmt, NULL),
*/
- __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_get_val); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 433; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_db, __pyx_n_s_get_val); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_5 = PyUnicode_Format(__pyx_kp_u_PRAGMA_s, __pyx_v_pragma); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 433; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyUnicode_Format(__pyx_kp_u_PRAGMA_s, __pyx_v_pragma); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 433; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_1, __pyx_t_12, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 433; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_12, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_XDECREF_SET(__pyx_v_val, __pyx_t_5);
__pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":434
+ /* "s3ql/deltadump.pyx":443
* for pragma in ('synchronous', 'foreign_keys'):
* val = db.get_val('PRAGMA %s' % pragma)
* cmd = ('PRAGMA %s = %s' % (pragma, val)).encode('utf-8') # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, cmd, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 434; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 443; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_INCREF(__pyx_v_pragma);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_pragma);
@@ -5159,34 +5169,34 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__Pyx_INCREF(__pyx_v_val);
PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_v_val);
__Pyx_GIVEREF(__pyx_v_val);
- __pyx_t_12 = PyUnicode_Format(__pyx_kp_u_PRAGMA_s_s, __pyx_t_5); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 434; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyUnicode_Format(__pyx_kp_u_PRAGMA_s_s, __pyx_t_5); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 443; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_5 = PyUnicode_AsUTF8String(((PyObject*)__pyx_t_12)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 434; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyUnicode_AsUTF8String(((PyObject*)__pyx_t_12)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 443; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_XDECREF_SET(__pyx_v_cmd, __pyx_t_5);
__pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":435
+ /* "s3ql/deltadump.pyx":444
* val = db.get_val('PRAGMA %s' % pragma)
* cmd = ('PRAGMA %s = %s' % (pragma, val)).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, cmd, -1, &stmt, NULL), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
* try:
*/
- __pyx_t_13 = __Pyx_PyObject_AsString(__pyx_v_cmd); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_13 = __Pyx_PyObject_AsString(__pyx_v_cmd); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":436
+ /* "s3ql/deltadump.pyx":445
* cmd = ('PRAGMA %s = %s' % (pragma, val)).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, cmd, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
* try:
* rc = sqlite3_step(stmt)
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_13, -1, (&__pyx_cur_scope->__pyx_v_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_13, -1, (&__pyx_cur_scope->__pyx_v_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":437
+ /* "s3ql/deltadump.pyx":446
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, cmd, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
* try: # <<<<<<<<<<<<<<
@@ -5195,7 +5205,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
/*try:*/ {
- /* "s3ql/deltadump.pyx":438
+ /* "s3ql/deltadump.pyx":447
* SQLITE_OK, sqlite3_db)
* try:
* rc = sqlite3_step(stmt) # <<<<<<<<<<<<<<
@@ -5204,7 +5214,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_rc = sqlite3_step(__pyx_cur_scope->__pyx_v_stmt);
- /* "s3ql/deltadump.pyx":439
+ /* "s3ql/deltadump.pyx":448
* try:
* rc = sqlite3_step(stmt)
* if rc == SQLITE_ROW: # <<<<<<<<<<<<<<
@@ -5214,7 +5224,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = ((__pyx_v_rc == SQLITE_ROW) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":440
+ /* "s3ql/deltadump.pyx":449
* rc = sqlite3_step(stmt)
* if rc == SQLITE_ROW:
* rc = sqlite3_step(stmt) # <<<<<<<<<<<<<<
@@ -5226,17 +5236,17 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
}
__pyx_L24:;
- /* "s3ql/deltadump.pyx":441
+ /* "s3ql/deltadump.pyx":450
* if rc == SQLITE_ROW:
* rc = sqlite3_step(stmt)
* SQLITE_CHECK_RC(rc, SQLITE_DONE, sqlite3_db) # <<<<<<<<<<<<<<
* finally:
* SQLITE_CHECK_RC(sqlite3_finalize(stmt), SQLITE_OK, sqlite3_db)
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(__pyx_v_rc, SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L22_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(__pyx_v_rc, SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 450; __pyx_clineno = __LINE__; goto __pyx_L22_error;}
}
- /* "s3ql/deltadump.pyx":443
+ /* "s3ql/deltadump.pyx":452
* SQLITE_CHECK_RC(rc, SQLITE_DONE, sqlite3_db)
* finally:
* SQLITE_CHECK_RC(sqlite3_finalize(stmt), SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
@@ -5245,7 +5255,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
/*finally:*/ {
/*normal exit:*/{
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 443; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L23;
}
/*exception exit:*/{
@@ -5264,7 +5274,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__Pyx_XGOTREF(__pyx_t_21);
__pyx_t_10 = __pyx_lineno; __pyx_t_14 = __pyx_clineno; __pyx_t_15 = __pyx_filename;
{
- __pyx_t_22 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_22 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 443; __pyx_clineno = __LINE__; goto __pyx_L28_error;}
+ __pyx_t_22 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_finalize(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_22 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L28_error;}
}
if (PY_MAJOR_VERSION >= 3) {
__Pyx_XGIVEREF(__pyx_t_19);
@@ -5297,126 +5307,126 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":446
+ /* "s3ql/deltadump.pyx":455
*
* # Get FILE* for buffered reading from *fh*
* fp = dup_to_fp(fh, b'rb') # <<<<<<<<<<<<<<
* cm.callback(lambda: fclose(fp))
*
*/
- __pyx_t_23 = __pyx_f_4s3ql_9deltadump_dup_to_fp(__pyx_v_fh, __pyx_k_rb); if (unlikely(__pyx_t_23 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 446; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_23 = __pyx_f_4s3ql_9deltadump_dup_to_fp(__pyx_v_fh, __pyx_k_rb); if (unlikely(__pyx_t_23 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 455; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__pyx_cur_scope->__pyx_v_fp = __pyx_t_23;
- /* "s3ql/deltadump.pyx":447
+ /* "s3ql/deltadump.pyx":456
* # Get FILE* for buffered reading from *fh*
* fp = dup_to_fp(fh, b'rb')
* cm.callback(lambda: fclose(fp)) # <<<<<<<<<<<<<<
*
* # Allocate col_args and col_types
*/
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_5 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_1lambda8, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_1lambda8, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_3, __pyx_t_12, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_12, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":450
+ /* "s3ql/deltadump.pyx":459
*
* # Allocate col_args and col_types
* col_count = prep_columns(columns, &col_types, &col_args) # <<<<<<<<<<<<<<
* cm.callback(lambda: free(col_args))
* cm.callback(lambda: free(col_types))
*/
- __pyx_t_14 = __pyx_f_4s3ql_9deltadump_prep_columns(__pyx_v_columns, (&__pyx_cur_scope->__pyx_v_col_types), (&__pyx_cur_scope->__pyx_v_col_args)); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 450; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_14 = __pyx_f_4s3ql_9deltadump_prep_columns(__pyx_v_columns, (&__pyx_cur_scope->__pyx_v_col_types), (&__pyx_cur_scope->__pyx_v_col_args)); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__pyx_v_col_count = __pyx_t_14;
- /* "s3ql/deltadump.pyx":451
+ /* "s3ql/deltadump.pyx":460
* # Allocate col_args and col_types
* col_count = prep_columns(columns, &col_types, &col_args)
* cm.callback(lambda: free(col_args)) # <<<<<<<<<<<<<<
* cm.callback(lambda: free(col_types))
*
*/
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 460; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_12 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_2lambda9, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_2lambda9, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 460; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 460; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_12);
__Pyx_GIVEREF(__pyx_t_12);
__pyx_t_12 = 0;
- __pyx_t_12 = PyObject_Call(__pyx_t_5, __pyx_t_3, NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_3, NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 460; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
- /* "s3ql/deltadump.pyx":452
+ /* "s3ql/deltadump.pyx":461
* col_count = prep_columns(columns, &col_types, &col_args)
* cm.callback(lambda: free(col_args))
* cm.callback(lambda: free(col_types)) # <<<<<<<<<<<<<<
*
* # Allocate int64_prev
*/
- __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_3lambda10, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_3lambda10, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_12, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":455
+ /* "s3ql/deltadump.pyx":464
*
* # Allocate int64_prev
* int64_prev = < int64_t *> calloc(len(columns), sizeof(int64_t)) # <<<<<<<<<<<<<<
* cm.callback(lambda: free(int64_prev))
*
*/
- __pyx_t_11 = PyObject_Length(__pyx_v_columns); if (unlikely(__pyx_t_11 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 455; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- __pyx_t_24 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_t_11, (sizeof(int64_t))); if (unlikely(__pyx_t_24 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 455; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_11 = PyObject_Length(__pyx_v_columns); if (unlikely(__pyx_t_11 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 464; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_24 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_t_11, (sizeof(int64_t))); if (unlikely(__pyx_t_24 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 464; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__pyx_cur_scope->__pyx_v_int64_prev = ((int64_t *)__pyx_t_24);
- /* "s3ql/deltadump.pyx":456
+ /* "s3ql/deltadump.pyx":465
* # Allocate int64_prev
* int64_prev = < int64_t *> calloc(len(columns), sizeof(int64_t))
* cm.callback(lambda: free(int64_prev)) # <<<<<<<<<<<<<<
*
* # Prepare INSERT statement
*/
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_5 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_4lambda11, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_4lambda11, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_3, __pyx_t_12, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 456; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_12, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":459
+ /* "s3ql/deltadump.pyx":468
*
* # Prepare INSERT statement
* col_names = [ x[0] for x in columns ] # <<<<<<<<<<<<<<
@@ -5425,13 +5435,13 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
{ /* enter inner scope */
PyObject *__pyx_8genexpr1__pyx_v_x = NULL;
- __pyx_t_5 = PyList_New(0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+ __pyx_t_5 = PyList_New(0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
__Pyx_GOTREF(__pyx_t_5);
if (PyList_CheckExact(__pyx_v_columns) || PyTuple_CheckExact(__pyx_v_columns)) {
__pyx_t_12 = __pyx_v_columns; __Pyx_INCREF(__pyx_t_12); __pyx_t_11 = 0;
__pyx_t_25 = NULL;
} else {
- __pyx_t_11 = -1; __pyx_t_12 = PyObject_GetIter(__pyx_v_columns); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+ __pyx_t_11 = -1; __pyx_t_12 = PyObject_GetIter(__pyx_v_columns); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_25 = Py_TYPE(__pyx_t_12)->tp_iternext;
}
@@ -5439,16 +5449,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
if (!__pyx_t_25 && PyList_CheckExact(__pyx_t_12)) {
if (__pyx_t_11 >= PyList_GET_SIZE(__pyx_t_12)) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_3 = PyList_GET_ITEM(__pyx_t_12, __pyx_t_11); __Pyx_INCREF(__pyx_t_3); __pyx_t_11++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+ __pyx_t_3 = PyList_GET_ITEM(__pyx_t_12, __pyx_t_11); __Pyx_INCREF(__pyx_t_3); __pyx_t_11++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
#else
- __pyx_t_3 = PySequence_ITEM(__pyx_t_12, __pyx_t_11); __pyx_t_11++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+ __pyx_t_3 = PySequence_ITEM(__pyx_t_12, __pyx_t_11); __pyx_t_11++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
#endif
} else if (!__pyx_t_25 && PyTuple_CheckExact(__pyx_t_12)) {
if (__pyx_t_11 >= PyTuple_GET_SIZE(__pyx_t_12)) break;
#if CYTHON_COMPILING_IN_CPYTHON
- __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_12, __pyx_t_11); __Pyx_INCREF(__pyx_t_3); __pyx_t_11++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+ __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_12, __pyx_t_11); __Pyx_INCREF(__pyx_t_3); __pyx_t_11++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
#else
- __pyx_t_3 = PySequence_ITEM(__pyx_t_12, __pyx_t_11); __pyx_t_11++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+ __pyx_t_3 = PySequence_ITEM(__pyx_t_12, __pyx_t_11); __pyx_t_11++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
#endif
} else {
__pyx_t_3 = __pyx_t_25(__pyx_t_12);
@@ -5456,7 +5466,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
PyObject* exc_type = PyErr_Occurred();
if (exc_type) {
if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
- else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+ else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
}
break;
}
@@ -5464,9 +5474,9 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
}
__Pyx_XDECREF_SET(__pyx_8genexpr1__pyx_v_x, __pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = __Pyx_GetItemInt(__pyx_8genexpr1__pyx_v_x, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;};
+ __pyx_t_3 = __Pyx_GetItemInt(__pyx_8genexpr1__pyx_v_x, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(__pyx_t_3 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;};
__Pyx_GOTREF(__pyx_t_3);
- if (unlikely(__Pyx_ListComp_Append(__pyx_t_5, (PyObject*)__pyx_t_3))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
+ if (unlikely(__Pyx_ListComp_Append(__pyx_t_5, (PyObject*)__pyx_t_3))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 468; __pyx_clineno = __LINE__; goto __pyx_L31_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
}
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
@@ -5480,40 +5490,40 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_v_col_names = ((PyObject*)__pyx_t_5);
__pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":461
+ /* "s3ql/deltadump.pyx":470
* col_names = [ x[0] for x in columns ]
* query = ("INSERT INTO %s (%s) VALUES(%s)"
* % (table, ', '.join(col_names), # <<<<<<<<<<<<<<
* ', '.join('?' * col_count))).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
*/
- __pyx_t_5 = PyUnicode_Join(__pyx_kp_u__4, __pyx_v_col_names); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyUnicode_Join(__pyx_kp_u__4, __pyx_v_col_names); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- /* "s3ql/deltadump.pyx":462
+ /* "s3ql/deltadump.pyx":471
* query = ("INSERT INTO %s (%s) VALUES(%s)"
* % (table, ', '.join(col_names),
* ', '.join('?' * col_count))).encode('utf-8') # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_12 = __Pyx_PyInt_From_int(__pyx_v_col_count); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 462; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyInt_From_int(__pyx_v_col_count); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_3 = PyNumber_Multiply(__pyx_kp_u__9, __pyx_t_12); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 462; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyNumber_Multiply(__pyx_kp_u__9, __pyx_t_12); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
- __pyx_t_12 = PyUnicode_Join(__pyx_kp_u__4, __pyx_t_3); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 462; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyUnicode_Join(__pyx_kp_u__4, __pyx_t_3); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":461
+ /* "s3ql/deltadump.pyx":470
* col_names = [ x[0] for x in columns ]
* query = ("INSERT INTO %s (%s) VALUES(%s)"
* % (table, ', '.join(col_names), # <<<<<<<<<<<<<<
* ', '.join('?' * col_count))).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
*/
- __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_INCREF(__pyx_v_table);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_table);
@@ -5524,64 +5534,64 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__Pyx_GIVEREF(__pyx_t_12);
__pyx_t_5 = 0;
__pyx_t_12 = 0;
- __pyx_t_12 = PyUnicode_Format(__pyx_kp_u_INSERT_INTO_s_s_VALUES_s, __pyx_t_3); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyUnicode_Format(__pyx_kp_u_INSERT_INTO_s_s_VALUES_s, __pyx_t_3); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":462
+ /* "s3ql/deltadump.pyx":471
* query = ("INSERT INTO %s (%s) VALUES(%s)"
* % (table, ', '.join(col_names),
* ', '.join('?' * col_count))).encode('utf-8') # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
*/
- __pyx_t_3 = PyUnicode_AsUTF8String(((PyObject*)__pyx_t_12)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 462; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyUnicode_AsUTF8String(((PyObject*)__pyx_t_12)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__pyx_v_query = __pyx_t_3;
__pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":463
+ /* "s3ql/deltadump.pyx":472
* % (table, ', '.join(col_names),
* ', '.join('?' * col_count))).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt),
*/
- __pyx_t_13 = __Pyx_PyObject_AsString(__pyx_v_query); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 463; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_13 = __Pyx_PyObject_AsString(__pyx_v_query); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":464
+ /* "s3ql/deltadump.pyx":473
* ', '.join('?' * col_count))).encode('utf-8')
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt),
* SQLITE_OK, sqlite3_db))
*/
- __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_13, -1, (&__pyx_cur_scope->__pyx_v_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 463; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_13, -1, (&__pyx_cur_scope->__pyx_v_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":465
+ /* "s3ql/deltadump.pyx":474
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(stmt), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
*
*/
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_12 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_5lambda12, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_5lambda12, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_12);
__Pyx_GIVEREF(__pyx_t_12);
__pyx_t_12 = 0;
- __pyx_t_12 = PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
- /* "s3ql/deltadump.pyx":469
+ /* "s3ql/deltadump.pyx":478
*
* # Prepare BEGIN statement
* query = b'BEGIN TRANSACTION' # <<<<<<<<<<<<<<
@@ -5591,47 +5601,47 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__Pyx_INCREF(__pyx_kp_b_BEGIN_TRANSACTION);
__Pyx_DECREF_SET(__pyx_v_query, __pyx_kp_b_BEGIN_TRANSACTION);
- /* "s3ql/deltadump.pyx":470
+ /* "s3ql/deltadump.pyx":479
* # Prepare BEGIN statement
* query = b'BEGIN TRANSACTION'
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &begin_stmt, NULL), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(begin_stmt),
*/
- __pyx_t_13 = __Pyx_PyObject_AsString(__pyx_v_query); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_13 = __Pyx_PyObject_AsString(__pyx_v_query); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":471
+ /* "s3ql/deltadump.pyx":480
* query = b'BEGIN TRANSACTION'
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &begin_stmt, NULL),
* SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(begin_stmt),
* SQLITE_OK, sqlite3_db))
*/
- __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_13, -1, (&__pyx_cur_scope->__pyx_v_begin_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_13, -1, (&__pyx_cur_scope->__pyx_v_begin_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":472
+ /* "s3ql/deltadump.pyx":481
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &begin_stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(begin_stmt), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
*
*/
- __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 481; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_5 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_6lambda13, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_6lambda13, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 481; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 481; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_t_12, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 481; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":476
+ /* "s3ql/deltadump.pyx":485
*
* # Prepare COMMIT statement
* query = b'COMMIT TRANSACTION' # <<<<<<<<<<<<<<
@@ -5641,106 +5651,106 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__Pyx_INCREF(__pyx_kp_b_COMMIT_TRANSACTION);
__Pyx_DECREF_SET(__pyx_v_query, __pyx_kp_b_COMMIT_TRANSACTION);
- /* "s3ql/deltadump.pyx":477
+ /* "s3ql/deltadump.pyx":486
* # Prepare COMMIT statement
* query = b'COMMIT TRANSACTION'
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &commit_stmt, NULL), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(commit_stmt),
*/
- __pyx_t_13 = __Pyx_PyObject_AsString(__pyx_v_query); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 477; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_13 = __Pyx_PyObject_AsString(__pyx_v_query); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 486; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":478
+ /* "s3ql/deltadump.pyx":487
* query = b'COMMIT TRANSACTION'
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &commit_stmt, NULL),
* SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(commit_stmt),
* SQLITE_OK, sqlite3_db))
*/
- __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_13, -1, (&__pyx_cur_scope->__pyx_v_commit_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 477; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_prepare_v2(__pyx_cur_scope->__pyx_v_sqlite3_db, __pyx_t_13, -1, (&__pyx_cur_scope->__pyx_v_commit_stmt), NULL), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 486; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":479
+ /* "s3ql/deltadump.pyx":488
* SQLITE_CHECK_RC(sqlite3_prepare_v2(sqlite3_db, query, -1, &commit_stmt, NULL),
* SQLITE_OK, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_finalize(commit_stmt), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db))
*
*/
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_7lambda14, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_7lambda14, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_5, __pyx_t_12, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 479; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_12, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":482
+ /* "s3ql/deltadump.pyx":491
* SQLITE_OK, sqlite3_db))
*
* buf = calloc(MAX_BLOB_SIZE, 1) # <<<<<<<<<<<<<<
* cm.callback(lambda: free(buf))
* read_integer(&row_count, fp)
*/
- __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 482; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_26 = __Pyx_PyInt_As_size_t(__pyx_t_3); if (unlikely((__pyx_t_26 == (size_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 482; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_26 = __Pyx_PyInt_As_size_t(__pyx_t_3); if (unlikely((__pyx_t_26 == (size_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_24 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_t_26, 1); if (unlikely(__pyx_t_24 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 482; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_24 = __pyx_f_4s3ql_9deltadump_calloc(__pyx_t_26, 1); if (unlikely(__pyx_t_24 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__pyx_cur_scope->__pyx_v_buf = __pyx_t_24;
- /* "s3ql/deltadump.pyx":483
+ /* "s3ql/deltadump.pyx":492
*
* buf = calloc(MAX_BLOB_SIZE, 1)
* cm.callback(lambda: free(buf)) # <<<<<<<<<<<<<<
* read_integer(&row_count, fp)
* log.debug('load_table(%s): reading %d rows', table, row_count)
*/
- __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 483; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_12 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_8lambda15, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 483; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_8lambda15, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 483; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_12);
__Pyx_GIVEREF(__pyx_t_12);
__pyx_t_12 = 0;
- __pyx_t_12 = PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 483; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
- /* "s3ql/deltadump.pyx":484
+ /* "s3ql/deltadump.pyx":493
* buf = calloc(MAX_BLOB_SIZE, 1)
* cm.callback(lambda: free(buf))
* read_integer(&row_count, fp) # <<<<<<<<<<<<<<
* log.debug('load_table(%s): reading %d rows', table, row_count)
*
*/
- __pyx_t_14 = __pyx_f_4s3ql_9deltadump_read_integer((&__pyx_v_row_count), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 484; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_14 = __pyx_f_4s3ql_9deltadump_read_integer((&__pyx_v_row_count), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 493; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":485
+ /* "s3ql/deltadump.pyx":494
* cm.callback(lambda: free(buf))
* read_integer(&row_count, fp)
* log.debug('load_table(%s): reading %d rows', table, row_count) # <<<<<<<<<<<<<<
*
* # Start transaction
*/
- __pyx_t_12 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 485; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_GetModuleGlobalName(__pyx_n_s_log); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_n_s_debug); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 485; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_n_s_debug); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
- __pyx_t_12 = __Pyx_PyInt_From_int64_t(__pyx_v_row_count); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 485; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyInt_From_int64_t(__pyx_v_row_count); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 485; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_INCREF(__pyx_kp_u_load_table_s_reading_d_rows);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_kp_u_load_table_s_reading_d_rows);
@@ -5751,53 +5761,53 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_12);
__Pyx_GIVEREF(__pyx_t_12);
__pyx_t_12 = 0;
- __pyx_t_12 = PyObject_Call(__pyx_t_5, __pyx_t_3, NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 485; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_3, NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
- /* "s3ql/deltadump.pyx":488
+ /* "s3ql/deltadump.pyx":497
*
* # Start transaction
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db) # <<<<<<<<<<<<<<
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_step(commit_stmt),
* SQLITE_DONE, sqlite3_db))
*/
- __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 488; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 497; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":489
+ /* "s3ql/deltadump.pyx":498
* # Start transaction
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db)
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_step(commit_stmt), # <<<<<<<<<<<<<<
* SQLITE_DONE, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_reset(begin_stmt), SQLITE_OK, sqlite3_db)
*/
- __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_v_cm, __pyx_n_s_callback); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 498; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_9lambda16, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_10load_table_9lambda16, 0, __pyx_n_s_load_table_locals_lambda, ((PyObject*)__pyx_cur_scope), __pyx_n_s_s3ql_deltadump, PyModule_GetDict(__pyx_m), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 498; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 498; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);
__Pyx_GIVEREF(__pyx_t_3);
__pyx_t_3 = 0;
- __pyx_t_3 = PyObject_Call(__pyx_t_12, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 489; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 498; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- /* "s3ql/deltadump.pyx":491
+ /* "s3ql/deltadump.pyx":500
* cm.callback(lambda: SQLITE_CHECK_RC(sqlite3_step(commit_stmt),
* SQLITE_DONE, sqlite3_db))
* SQLITE_CHECK_RC(sqlite3_reset(begin_stmt), SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
*
* # Iterate through rows
*/
- __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_reset(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 491; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_14 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_reset(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":494
+ /* "s3ql/deltadump.pyx":503
*
* # Iterate through rows
* for i in range(row_count): # <<<<<<<<<<<<<<
@@ -5808,7 +5818,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
for (__pyx_t_14 = 0; __pyx_t_14 < __pyx_t_27; __pyx_t_14+=1) {
__pyx_v_i = __pyx_t_14;
- /* "s3ql/deltadump.pyx":495
+ /* "s3ql/deltadump.pyx":504
* # Iterate through rows
* for i in range(row_count):
* for j in range(col_count): # <<<<<<<<<<<<<<
@@ -5819,7 +5829,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
for (__pyx_t_22 = 0; __pyx_t_22 < __pyx_t_10; __pyx_t_22+=1) {
__pyx_v_j = __pyx_t_22;
- /* "s3ql/deltadump.pyx":496
+ /* "s3ql/deltadump.pyx":505
* for i in range(row_count):
* for j in range(col_count):
* if col_types[j] == _INTEGER: # <<<<<<<<<<<<<<
@@ -5829,16 +5839,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = (((__pyx_cur_scope->__pyx_v_col_types[__pyx_v_j]) == __pyx_v_4s3ql_9deltadump__INTEGER) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":497
+ /* "s3ql/deltadump.pyx":506
* for j in range(col_count):
* if col_types[j] == _INTEGER:
* read_integer(&int64, fp) # <<<<<<<<<<<<<<
* int64 += col_args[j] + int64_prev[j]
* int64_prev[j] = int64
*/
- __pyx_t_28 = __pyx_f_4s3ql_9deltadump_read_integer((&__pyx_v_int64), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 497; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_28 = __pyx_f_4s3ql_9deltadump_read_integer((&__pyx_v_int64), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 506; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":498
+ /* "s3ql/deltadump.pyx":507
* if col_types[j] == _INTEGER:
* read_integer(&int64, fp)
* int64 += col_args[j] + int64_prev[j] # <<<<<<<<<<<<<<
@@ -5847,7 +5857,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_int64 = (__pyx_v_int64 + ((__pyx_cur_scope->__pyx_v_col_args[__pyx_v_j]) + (__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_j])));
- /* "s3ql/deltadump.pyx":499
+ /* "s3ql/deltadump.pyx":508
* read_integer(&int64, fp)
* int64 += col_args[j] + int64_prev[j]
* int64_prev[j] = int64 # <<<<<<<<<<<<<<
@@ -5856,19 +5866,19 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
(__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_j]) = __pyx_v_int64;
- /* "s3ql/deltadump.pyx":500
+ /* "s3ql/deltadump.pyx":509
* int64 += col_args[j] + int64_prev[j]
* int64_prev[j] = int64
* SQLITE_CHECK_RC(sqlite3_bind_int64(stmt, j + 1, int64), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
*
*/
- __pyx_t_28 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_bind_int64(__pyx_cur_scope->__pyx_v_stmt, (__pyx_v_j + 1), __pyx_v_int64), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 500; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_28 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_bind_int64(__pyx_cur_scope->__pyx_v_stmt, (__pyx_v_j + 1), __pyx_v_int64), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 509; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L39;
}
__pyx_L39:;
- /* "s3ql/deltadump.pyx":503
+ /* "s3ql/deltadump.pyx":512
* SQLITE_OK, sqlite3_db)
*
* if col_types[j] == _TIME: # <<<<<<<<<<<<<<
@@ -5878,16 +5888,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = (((__pyx_cur_scope->__pyx_v_col_types[__pyx_v_j]) == __pyx_v_4s3ql_9deltadump__TIME) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":504
+ /* "s3ql/deltadump.pyx":513
*
* if col_types[j] == _TIME:
* read_integer(&int64, fp) # <<<<<<<<<<<<<<
* int64 += col_args[j] + int64_prev[j]
* int64_prev[j] = int64
*/
- __pyx_t_28 = __pyx_f_4s3ql_9deltadump_read_integer((&__pyx_v_int64), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_28 = __pyx_f_4s3ql_9deltadump_read_integer((&__pyx_v_int64), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 513; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":505
+ /* "s3ql/deltadump.pyx":514
* if col_types[j] == _TIME:
* read_integer(&int64, fp)
* int64 += col_args[j] + int64_prev[j] # <<<<<<<<<<<<<<
@@ -5896,7 +5906,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_int64 = (__pyx_v_int64 + ((__pyx_cur_scope->__pyx_v_col_args[__pyx_v_j]) + (__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_j])));
- /* "s3ql/deltadump.pyx":506
+ /* "s3ql/deltadump.pyx":515
* read_integer(&int64, fp)
* int64 += col_args[j] + int64_prev[j]
* int64_prev[j] = int64 # <<<<<<<<<<<<<<
@@ -5905,7 +5915,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
(__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_j]) = __pyx_v_int64;
- /* "s3ql/deltadump.pyx":507
+ /* "s3ql/deltadump.pyx":516
* int64 += col_args[j] + int64_prev[j]
* int64_prev[j] = int64
* SQLITE_CHECK_RC(sqlite3_bind_double(stmt, j + 1, int64 / time_scale), # <<<<<<<<<<<<<<
@@ -5920,21 +5930,21 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
#ifdef WITH_THREAD
PyGILState_Release(__pyx_gilstate_save);
#endif
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 507; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 516; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
}
- /* "s3ql/deltadump.pyx":508
+ /* "s3ql/deltadump.pyx":517
* int64_prev[j] = int64
* SQLITE_CHECK_RC(sqlite3_bind_double(stmt, j + 1, int64 / time_scale),
* SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
*
* elif col_types[j] == _BLOB:
*/
- __pyx_t_28 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_bind_double(__pyx_cur_scope->__pyx_v_stmt, (__pyx_v_j + 1), (__pyx_v_int64 / __pyx_v_4s3ql_9deltadump_time_scale)), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 507; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_28 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_bind_double(__pyx_cur_scope->__pyx_v_stmt, (__pyx_v_j + 1), (__pyx_v_int64 / __pyx_v_4s3ql_9deltadump_time_scale)), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 516; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L40;
}
- /* "s3ql/deltadump.pyx":510
+ /* "s3ql/deltadump.pyx":519
* SQLITE_OK, sqlite3_db)
*
* elif col_types[j] == _BLOB: # <<<<<<<<<<<<<<
@@ -5944,7 +5954,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = (((__pyx_cur_scope->__pyx_v_col_types[__pyx_v_j]) == __pyx_v_4s3ql_9deltadump__BLOB) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":511
+ /* "s3ql/deltadump.pyx":520
*
* elif col_types[j] == _BLOB:
* if col_args[j] == 0: # <<<<<<<<<<<<<<
@@ -5954,16 +5964,16 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = (((__pyx_cur_scope->__pyx_v_col_args[__pyx_v_j]) == 0) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":512
+ /* "s3ql/deltadump.pyx":521
* elif col_types[j] == _BLOB:
* if col_args[j] == 0:
* read_integer(&int64, fp) # <<<<<<<<<<<<<<
* len_ = int64_prev[j] + int64
* int64_prev[j] = len_
*/
- __pyx_t_28 = __pyx_f_4s3ql_9deltadump_read_integer((&__pyx_v_int64), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 512; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_28 = __pyx_f_4s3ql_9deltadump_read_integer((&__pyx_v_int64), __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 521; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":513
+ /* "s3ql/deltadump.pyx":522
* if col_args[j] == 0:
* read_integer(&int64, fp)
* len_ = int64_prev[j] + int64 # <<<<<<<<<<<<<<
@@ -5972,7 +5982,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
__pyx_v_len_ = ((__pyx_cur_scope->__pyx_v_int64_prev[__pyx_v_j]) + __pyx_v_int64);
- /* "s3ql/deltadump.pyx":514
+ /* "s3ql/deltadump.pyx":523
* read_integer(&int64, fp)
* len_ = int64_prev[j] + int64
* int64_prev[j] = len_ # <<<<<<<<<<<<<<
@@ -5984,7 +5994,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
}
/*else*/ {
- /* "s3ql/deltadump.pyx":516
+ /* "s3ql/deltadump.pyx":525
* int64_prev[j] = len_
* else:
* len_ = col_args[j] # <<<<<<<<<<<<<<
@@ -5995,36 +6005,36 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
}
__pyx_L41:;
- /* "s3ql/deltadump.pyx":518
+ /* "s3ql/deltadump.pyx":527
* len_ = col_args[j]
*
* if len_ > MAX_BLOB_SIZE: # <<<<<<<<<<<<<<
* raise RuntimeError('BLOB too large to read (%d vs %d)', len_, MAX_BLOB_SIZE)
*
*/
- __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 527; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
- __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 527; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_12 = PyObject_RichCompare(__pyx_t_3, __pyx_t_5, Py_GT); __Pyx_XGOTREF(__pyx_t_12); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = PyObject_RichCompare(__pyx_t_3, __pyx_t_5, Py_GT); __Pyx_XGOTREF(__pyx_t_12); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 527; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_12); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_12); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 527; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":519
+ /* "s3ql/deltadump.pyx":528
*
* if len_ > MAX_BLOB_SIZE:
* raise RuntimeError('BLOB too large to read (%d vs %d)', len_, MAX_BLOB_SIZE) # <<<<<<<<<<<<<<
*
* if len_ != 0:
*/
- __pyx_t_12 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 519; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_12 = __Pyx_PyInt_From_int(__pyx_v_len_); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 528; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 519; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_MAX_BLOB_SIZE); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 528; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 519; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 528; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_INCREF(__pyx_kp_u_BLOB_too_large_to_read_d_vs_d);
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_kp_u_BLOB_too_large_to_read_d_vs_d);
@@ -6035,15 +6045,15 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__Pyx_GIVEREF(__pyx_t_5);
__pyx_t_12 = 0;
__pyx_t_5 = 0;
- __pyx_t_5 = PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 519; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 528; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_Raise(__pyx_t_5, 0, 0, 0);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 519; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 528; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
}
- /* "s3ql/deltadump.pyx":521
+ /* "s3ql/deltadump.pyx":530
* raise RuntimeError('BLOB too large to read (%d vs %d)', len_, MAX_BLOB_SIZE)
*
* if len_ != 0: # <<<<<<<<<<<<<<
@@ -6053,102 +6063,102 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_t_2 = ((__pyx_v_len_ != 0) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":522
+ /* "s3ql/deltadump.pyx":531
*
* if len_ != 0:
* fread(buf, len_, fp) # <<<<<<<<<<<<<<
*
* SQLITE_CHECK_RC(sqlite3_bind_blob(stmt, j + 1, buf, len_, SQLITE_TRANSIENT),
*/
- __pyx_t_28 = __pyx_f_4s3ql_9deltadump_fread(__pyx_cur_scope->__pyx_v_buf, __pyx_v_len_, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 522; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_28 = __pyx_f_4s3ql_9deltadump_fread(__pyx_cur_scope->__pyx_v_buf, __pyx_v_len_, __pyx_cur_scope->__pyx_v_fp); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L43;
}
__pyx_L43:;
- /* "s3ql/deltadump.pyx":524
+ /* "s3ql/deltadump.pyx":533
* fread(buf, len_, fp)
*
* SQLITE_CHECK_RC(sqlite3_bind_blob(stmt, j + 1, buf, len_, SQLITE_TRANSIENT), # <<<<<<<<<<<<<<
* SQLITE_OK, sqlite3_db)
*
*/
- __pyx_t_28 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_bind_blob(__pyx_cur_scope->__pyx_v_stmt, (__pyx_v_j + 1), __pyx_cur_scope->__pyx_v_buf, __pyx_v_len_, SQLITE_TRANSIENT), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 524; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_28 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_bind_blob(__pyx_cur_scope->__pyx_v_stmt, (__pyx_v_j + 1), __pyx_cur_scope->__pyx_v_buf, __pyx_v_len_, SQLITE_TRANSIENT), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_28 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 533; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L40;
}
__pyx_L40:;
}
- /* "s3ql/deltadump.pyx":527
+ /* "s3ql/deltadump.pyx":536
* SQLITE_OK, sqlite3_db)
*
* SQLITE_CHECK_RC(sqlite3_step(stmt), SQLITE_DONE, sqlite3_db) # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_reset(stmt), SQLITE_OK, sqlite3_db)
*
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 527; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":528
+ /* "s3ql/deltadump.pyx":537
*
* SQLITE_CHECK_RC(sqlite3_step(stmt), SQLITE_DONE, sqlite3_db)
* SQLITE_CHECK_RC(sqlite3_reset(stmt), SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
*
* # Commit every once in a while
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_reset(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 528; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_reset(__pyx_cur_scope->__pyx_v_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 537; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":531
+ /* "s3ql/deltadump.pyx":540
*
* # Commit every once in a while
* if i % trx_rows == 0: # <<<<<<<<<<<<<<
* # This isn't 100% ok -- if we have an exception in step(begin_stmt),
* # we the cleanup handler will execute the commit statement again
*/
- __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 540; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_5);
- __pyx_t_3 = PyNumber_Remainder(__pyx_t_5, __pyx_v_trx_rows); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_3 = PyNumber_Remainder(__pyx_t_5, __pyx_v_trx_rows); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 540; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_GOTREF(__pyx_t_3);
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
- __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_0, Py_EQ); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_int_0, Py_EQ); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 540; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
- __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 540; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":535
+ /* "s3ql/deltadump.pyx":544
* # we the cleanup handler will execute the commit statement again
* # without an active transaction.
* SQLITE_CHECK_RC(sqlite3_step(commit_stmt), SQLITE_DONE, sqlite3_db) # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db)
* SQLITE_CHECK_RC(sqlite3_reset(commit_stmt), SQLITE_OK, sqlite3_db)
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_commit_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 535; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_commit_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 544; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":536
+ /* "s3ql/deltadump.pyx":545
* # without an active transaction.
* SQLITE_CHECK_RC(sqlite3_step(commit_stmt), SQLITE_DONE, sqlite3_db)
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db) # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_reset(commit_stmt), SQLITE_OK, sqlite3_db)
* SQLITE_CHECK_RC(sqlite3_reset(begin_stmt), SQLITE_OK, sqlite3_db)
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_step(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_DONE, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 545; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":537
+ /* "s3ql/deltadump.pyx":546
* SQLITE_CHECK_RC(sqlite3_step(commit_stmt), SQLITE_DONE, sqlite3_db)
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db)
* SQLITE_CHECK_RC(sqlite3_reset(commit_stmt), SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
* SQLITE_CHECK_RC(sqlite3_reset(begin_stmt), SQLITE_OK, sqlite3_db)
*
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_reset(__pyx_cur_scope->__pyx_v_commit_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 537; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_reset(__pyx_cur_scope->__pyx_v_commit_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 546; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
- /* "s3ql/deltadump.pyx":538
+ /* "s3ql/deltadump.pyx":547
* SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db)
* SQLITE_CHECK_RC(sqlite3_reset(commit_stmt), SQLITE_OK, sqlite3_db)
* SQLITE_CHECK_RC(sqlite3_reset(begin_stmt), SQLITE_OK, sqlite3_db) # <<<<<<<<<<<<<<
*
*
*/
- __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_reset(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 538; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
+ __pyx_t_10 = __pyx_f_4s3ql_9deltadump_SQLITE_CHECK_RC(sqlite3_reset(__pyx_cur_scope->__pyx_v_begin_stmt), SQLITE_OK, __pyx_cur_scope->__pyx_v_sqlite3_db); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 547; __pyx_clineno = __LINE__; goto __pyx_L8_error;}
goto __pyx_L44;
}
__pyx_L44:;
@@ -6164,7 +6174,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
__Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
- /* "s3ql/deltadump.pyx":419
+ /* "s3ql/deltadump.pyx":428
* raise ValueError("Can't access in-memory databases")
*
* with ExitStack() as cm: # <<<<<<<<<<<<<<
@@ -6173,20 +6183,20 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
*/
/*except:*/ {
__Pyx_AddTraceback("s3ql.deltadump.load_table", __pyx_clineno, __pyx_lineno, __pyx_filename);
- if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_3, &__pyx_t_12) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_3, &__pyx_t_12) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
__Pyx_GOTREF(__pyx_t_5);
__Pyx_GOTREF(__pyx_t_3);
__Pyx_GOTREF(__pyx_t_12);
- __pyx_t_1 = PyTuple_Pack(3, __pyx_t_5, __pyx_t_3, __pyx_t_12); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ __pyx_t_1 = PyTuple_Pack(3, __pyx_t_5, __pyx_t_3, __pyx_t_12); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
__Pyx_GOTREF(__pyx_t_1);
- __pyx_t_21 = PyObject_Call(__pyx_t_4, __pyx_t_1, NULL);
+ __pyx_t_21 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_1, NULL);
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- if (unlikely(!__pyx_t_21)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ if (unlikely(!__pyx_t_21)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
__Pyx_GOTREF(__pyx_t_21);
__pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_21);
__Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
- if (__pyx_t_2 < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ if (__pyx_t_2 < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
__pyx_t_29 = ((!(__pyx_t_2 != 0)) != 0);
if (__pyx_t_29) {
__Pyx_GIVEREF(__pyx_t_5);
@@ -6194,7 +6204,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__Pyx_XGIVEREF(__pyx_t_12);
__Pyx_ErrRestore(__pyx_t_5, __pyx_t_3, __pyx_t_12);
__pyx_t_5 = 0; __pyx_t_3 = 0; __pyx_t_12 = 0;
- {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
+ {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L10_except_error;}
}
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -6218,9 +6228,9 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
/*finally:*/ {
/*normal exit:*/{
if (__pyx_t_4) {
- __pyx_t_8 = PyObject_Call(__pyx_t_4, __pyx_tuple__10, NULL);
+ __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_tuple__10, NULL);
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
- if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_8);
__Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
}
@@ -6235,7 +6245,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
__pyx_L48:;
}
- /* "s3ql/deltadump.pyx":390
+ /* "s3ql/deltadump.pyx":395
* fwrite(buf, len_, fp)
*
* def load_table(table, columns, db, fh, trx_rows=5000): # <<<<<<<<<<<<<<
@@ -6267,7 +6277,7 @@ static PyObject *__pyx_pf_4s3ql_9deltadump_4load_table(CYTHON_UNUSED PyObject *_
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":541
+/* "s3ql/deltadump.pyx":550
*
*
* cdef inline int write_integer(int64_t int64, FILE * fp) except -1: # <<<<<<<<<<<<<<
@@ -6292,7 +6302,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
int __pyx_clineno = 0;
__Pyx_RefNannySetupContext("write_integer", 0);
- /* "s3ql/deltadump.pyx":551
+ /* "s3ql/deltadump.pyx":560
* cdef uint64_t uint64
*
* if int64 < 0: # <<<<<<<<<<<<<<
@@ -6302,7 +6312,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
__pyx_t_1 = ((__pyx_v_int64 < 0) != 0);
if (__pyx_t_1) {
- /* "s3ql/deltadump.pyx":552
+ /* "s3ql/deltadump.pyx":561
*
* if int64 < 0:
* uint64 = < uint64_t > -int64 # <<<<<<<<<<<<<<
@@ -6311,7 +6321,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
*/
__pyx_v_uint64 = ((uint64_t)(-__pyx_v_int64));
- /* "s3ql/deltadump.pyx":553
+ /* "s3ql/deltadump.pyx":562
* if int64 < 0:
* uint64 = < uint64_t > -int64
* int8 = < uint8_t > 0x80 # Highest bit set # <<<<<<<<<<<<<<
@@ -6323,7 +6333,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
}
/*else*/ {
- /* "s3ql/deltadump.pyx":555
+ /* "s3ql/deltadump.pyx":564
* int8 = < uint8_t > 0x80 # Highest bit set
* else:
* uint64 = < uint64_t > int64 # <<<<<<<<<<<<<<
@@ -6332,7 +6342,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
*/
__pyx_v_uint64 = ((uint64_t)__pyx_v_int64);
- /* "s3ql/deltadump.pyx":556
+ /* "s3ql/deltadump.pyx":565
* else:
* uint64 = < uint64_t > int64
* int8 = 0 # <<<<<<<<<<<<<<
@@ -6343,7 +6353,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
}
__pyx_L3:;
- /* "s3ql/deltadump.pyx":558
+ /* "s3ql/deltadump.pyx":567
* int8 = 0
*
* if uint64 < 0x80 and uint64 not in (INT8, INT16, INT32, INT64): # <<<<<<<<<<<<<<
@@ -6353,21 +6363,21 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
__pyx_t_1 = ((__pyx_v_uint64 < 0x80) != 0);
if (__pyx_t_1) {
__pyx_t_2 = __pyx_v_uint64;
- __pyx_t_3 = ((int)(__pyx_t_2 != __pyx_v_4s3ql_9deltadump_INT8));
+ __pyx_t_3 = ((__pyx_t_2 != __pyx_v_4s3ql_9deltadump_INT8) != 0);
if (__pyx_t_3) {
- __pyx_t_4 = ((int)(__pyx_t_2 != __pyx_v_4s3ql_9deltadump_INT16));
+ __pyx_t_4 = ((__pyx_t_2 != __pyx_v_4s3ql_9deltadump_INT16) != 0);
__pyx_t_5 = __pyx_t_4;
} else {
__pyx_t_5 = __pyx_t_3;
}
if (__pyx_t_5) {
- __pyx_t_3 = ((int)(__pyx_t_2 != __pyx_v_4s3ql_9deltadump_INT32));
+ __pyx_t_3 = ((__pyx_t_2 != __pyx_v_4s3ql_9deltadump_INT32) != 0);
__pyx_t_4 = __pyx_t_3;
} else {
__pyx_t_4 = __pyx_t_5;
}
if (__pyx_t_4) {
- __pyx_t_5 = ((int)(__pyx_t_2 != __pyx_v_4s3ql_9deltadump_INT64));
+ __pyx_t_5 = ((__pyx_t_2 != __pyx_v_4s3ql_9deltadump_INT64) != 0);
__pyx_t_3 = __pyx_t_5;
} else {
__pyx_t_3 = __pyx_t_4;
@@ -6379,7 +6389,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
}
if (__pyx_t_3) {
- /* "s3ql/deltadump.pyx":559
+ /* "s3ql/deltadump.pyx":568
*
* if uint64 < 0x80 and uint64 not in (INT8, INT16, INT32, INT64):
* len_ = 0 # <<<<<<<<<<<<<<
@@ -6388,7 +6398,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
*/
__pyx_v_len_ = 0;
- /* "s3ql/deltadump.pyx":560
+ /* "s3ql/deltadump.pyx":569
* if uint64 < 0x80 and uint64 not in (INT8, INT16, INT32, INT64):
* len_ = 0
* int8 += < uint8_t > uint64 # <<<<<<<<<<<<<<
@@ -6399,7 +6409,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
goto __pyx_L4;
}
- /* "s3ql/deltadump.pyx":561
+ /* "s3ql/deltadump.pyx":570
* len_ = 0
* int8 += < uint8_t > uint64
* elif uint64 < UINT8_MAX: # <<<<<<<<<<<<<<
@@ -6409,7 +6419,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
__pyx_t_3 = ((__pyx_v_uint64 < UINT8_MAX) != 0);
if (__pyx_t_3) {
- /* "s3ql/deltadump.pyx":562
+ /* "s3ql/deltadump.pyx":571
* int8 += < uint8_t > uint64
* elif uint64 < UINT8_MAX:
* len_ = 1 # <<<<<<<<<<<<<<
@@ -6418,7 +6428,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
*/
__pyx_v_len_ = 1;
- /* "s3ql/deltadump.pyx":563
+ /* "s3ql/deltadump.pyx":572
* elif uint64 < UINT8_MAX:
* len_ = 1
* int8 += INT8 # <<<<<<<<<<<<<<
@@ -6429,7 +6439,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
goto __pyx_L4;
}
- /* "s3ql/deltadump.pyx":564
+ /* "s3ql/deltadump.pyx":573
* len_ = 1
* int8 += INT8
* elif uint64 < UINT16_MAX: # <<<<<<<<<<<<<<
@@ -6439,7 +6449,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
__pyx_t_3 = ((__pyx_v_uint64 < UINT16_MAX) != 0);
if (__pyx_t_3) {
- /* "s3ql/deltadump.pyx":565
+ /* "s3ql/deltadump.pyx":574
* int8 += INT8
* elif uint64 < UINT16_MAX:
* len_ = 2 # <<<<<<<<<<<<<<
@@ -6448,7 +6458,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
*/
__pyx_v_len_ = 2;
- /* "s3ql/deltadump.pyx":566
+ /* "s3ql/deltadump.pyx":575
* elif uint64 < UINT16_MAX:
* len_ = 2
* int8 += INT16 # <<<<<<<<<<<<<<
@@ -6459,7 +6469,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
goto __pyx_L4;
}
- /* "s3ql/deltadump.pyx":567
+ /* "s3ql/deltadump.pyx":576
* len_ = 2
* int8 += INT16
* elif uint64 < UINT32_MAX: # <<<<<<<<<<<<<<
@@ -6469,7 +6479,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
__pyx_t_3 = ((__pyx_v_uint64 < UINT32_MAX) != 0);
if (__pyx_t_3) {
- /* "s3ql/deltadump.pyx":568
+ /* "s3ql/deltadump.pyx":577
* int8 += INT16
* elif uint64 < UINT32_MAX:
* len_ = 4 # <<<<<<<<<<<<<<
@@ -6478,7 +6488,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
*/
__pyx_v_len_ = 4;
- /* "s3ql/deltadump.pyx":569
+ /* "s3ql/deltadump.pyx":578
* elif uint64 < UINT32_MAX:
* len_ = 4
* int8 += INT32 # <<<<<<<<<<<<<<
@@ -6490,7 +6500,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
}
/*else*/ {
- /* "s3ql/deltadump.pyx":571
+ /* "s3ql/deltadump.pyx":580
* int8 += INT32
* else:
* len_ = 8 # <<<<<<<<<<<<<<
@@ -6499,7 +6509,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
*/
__pyx_v_len_ = 8;
- /* "s3ql/deltadump.pyx":572
+ /* "s3ql/deltadump.pyx":581
* else:
* len_ = 8
* int8 += INT64 # <<<<<<<<<<<<<<
@@ -6510,16 +6520,16 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
}
__pyx_L4:;
- /* "s3ql/deltadump.pyx":574
+ /* "s3ql/deltadump.pyx":583
* int8 += INT64
*
* fwrite(&int8, 1, fp) # <<<<<<<<<<<<<<
* if len_ != 0:
* uint64 = htole64(uint64)
*/
- __pyx_t_6 = __pyx_f_4s3ql_9deltadump_fwrite((&__pyx_v_int8), 1, __pyx_v_fp); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 574; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_6 = __pyx_f_4s3ql_9deltadump_fwrite((&__pyx_v_int8), 1, __pyx_v_fp); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 583; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":575
+ /* "s3ql/deltadump.pyx":584
*
* fwrite(&int8, 1, fp)
* if len_ != 0: # <<<<<<<<<<<<<<
@@ -6529,7 +6539,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
__pyx_t_3 = ((__pyx_v_len_ != 0) != 0);
if (__pyx_t_3) {
- /* "s3ql/deltadump.pyx":576
+ /* "s3ql/deltadump.pyx":585
* fwrite(&int8, 1, fp)
* if len_ != 0:
* uint64 = htole64(uint64) # <<<<<<<<<<<<<<
@@ -6538,19 +6548,19 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
*/
__pyx_v_uint64 = htole64(__pyx_v_uint64);
- /* "s3ql/deltadump.pyx":577
+ /* "s3ql/deltadump.pyx":586
* if len_ != 0:
* uint64 = htole64(uint64)
* fwrite(&uint64, len_, fp) # <<<<<<<<<<<<<<
*
* return len_ + 1
*/
- __pyx_t_6 = __pyx_f_4s3ql_9deltadump_fwrite((&__pyx_v_uint64), __pyx_v_len_, __pyx_v_fp); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 577; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_6 = __pyx_f_4s3ql_9deltadump_fwrite((&__pyx_v_uint64), __pyx_v_len_, __pyx_v_fp); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 586; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
goto __pyx_L5;
}
__pyx_L5:;
- /* "s3ql/deltadump.pyx":579
+ /* "s3ql/deltadump.pyx":588
* fwrite(&uint64, len_, fp)
*
* return len_ + 1 # <<<<<<<<<<<<<<
@@ -6560,7 +6570,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
__pyx_r = (__pyx_v_len_ + 1);
goto __pyx_L0;
- /* "s3ql/deltadump.pyx":541
+ /* "s3ql/deltadump.pyx":550
*
*
* cdef inline int write_integer(int64_t int64, FILE * fp) except -1: # <<<<<<<<<<<<<<
@@ -6577,7 +6587,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_write_integer(int64_t __pyx_v_
return __pyx_r;
}
-/* "s3ql/deltadump.pyx":581
+/* "s3ql/deltadump.pyx":590
* return len_ + 1
*
* cdef inline int read_integer(int64_t * out, FILE * fp) except -1: # <<<<<<<<<<<<<<
@@ -6599,16 +6609,16 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
int __pyx_clineno = 0;
__Pyx_RefNannySetupContext("read_integer", 0);
- /* "s3ql/deltadump.pyx":592
+ /* "s3ql/deltadump.pyx":601
* cdef char negative
*
* fread(&int8, 1, fp) # <<<<<<<<<<<<<<
*
* if int8 & 0x80 != 0:
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_fread((&__pyx_v_int8), 1, __pyx_v_fp); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 592; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_fread((&__pyx_v_int8), 1, __pyx_v_fp); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 601; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":594
+ /* "s3ql/deltadump.pyx":603
* fread(&int8, 1, fp)
*
* if int8 & 0x80 != 0: # <<<<<<<<<<<<<<
@@ -6618,7 +6628,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
__pyx_t_2 = (((__pyx_v_int8 & 0x80) != 0) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":595
+ /* "s3ql/deltadump.pyx":604
*
* if int8 & 0x80 != 0:
* negative = 1 # <<<<<<<<<<<<<<
@@ -6627,7 +6637,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
*/
__pyx_v_negative = 1;
- /* "s3ql/deltadump.pyx":596
+ /* "s3ql/deltadump.pyx":605
* if int8 & 0x80 != 0:
* negative = 1
* int8 = int8 & (~0x80) # <<<<<<<<<<<<<<
@@ -6639,7 +6649,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
}
/*else*/ {
- /* "s3ql/deltadump.pyx":598
+ /* "s3ql/deltadump.pyx":607
* int8 = int8 & (~0x80)
* else:
* negative = 0 # <<<<<<<<<<<<<<
@@ -6650,7 +6660,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
}
__pyx_L3:;
- /* "s3ql/deltadump.pyx":600
+ /* "s3ql/deltadump.pyx":609
* negative = 0
*
* if int8 == INT8: # <<<<<<<<<<<<<<
@@ -6660,7 +6670,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
__pyx_t_2 = ((__pyx_v_int8 == __pyx_v_4s3ql_9deltadump_INT8) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":601
+ /* "s3ql/deltadump.pyx":610
*
* if int8 == INT8:
* len_ = 1 # <<<<<<<<<<<<<<
@@ -6671,7 +6681,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
goto __pyx_L4;
}
- /* "s3ql/deltadump.pyx":602
+ /* "s3ql/deltadump.pyx":611
* if int8 == INT8:
* len_ = 1
* elif int8 == INT16: # <<<<<<<<<<<<<<
@@ -6681,7 +6691,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
__pyx_t_2 = ((__pyx_v_int8 == __pyx_v_4s3ql_9deltadump_INT16) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":603
+ /* "s3ql/deltadump.pyx":612
* len_ = 1
* elif int8 == INT16:
* len_ = 2 # <<<<<<<<<<<<<<
@@ -6692,7 +6702,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
goto __pyx_L4;
}
- /* "s3ql/deltadump.pyx":604
+ /* "s3ql/deltadump.pyx":613
* elif int8 == INT16:
* len_ = 2
* elif int8 == INT32: # <<<<<<<<<<<<<<
@@ -6702,7 +6712,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
__pyx_t_2 = ((__pyx_v_int8 == __pyx_v_4s3ql_9deltadump_INT32) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":605
+ /* "s3ql/deltadump.pyx":614
* len_ = 2
* elif int8 == INT32:
* len_ = 4 # <<<<<<<<<<<<<<
@@ -6713,7 +6723,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
goto __pyx_L4;
}
- /* "s3ql/deltadump.pyx":606
+ /* "s3ql/deltadump.pyx":615
* elif int8 == INT32:
* len_ = 4
* elif int8 == INT64: # <<<<<<<<<<<<<<
@@ -6723,7 +6733,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
__pyx_t_2 = ((__pyx_v_int8 == __pyx_v_4s3ql_9deltadump_INT64) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":607
+ /* "s3ql/deltadump.pyx":616
* len_ = 4
* elif int8 == INT64:
* len_ = 8 # <<<<<<<<<<<<<<
@@ -6735,7 +6745,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
}
/*else*/ {
- /* "s3ql/deltadump.pyx":609
+ /* "s3ql/deltadump.pyx":618
* len_ = 8
* else:
* len_ = 0 # <<<<<<<<<<<<<<
@@ -6744,7 +6754,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
*/
__pyx_v_len_ = 0;
- /* "s3ql/deltadump.pyx":610
+ /* "s3ql/deltadump.pyx":619
* else:
* len_ = 0
* uint64 = int8 # <<<<<<<<<<<<<<
@@ -6755,7 +6765,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
}
__pyx_L4:;
- /* "s3ql/deltadump.pyx":612
+ /* "s3ql/deltadump.pyx":621
* uint64 = int8
*
* if len_ != 0: # <<<<<<<<<<<<<<
@@ -6765,7 +6775,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
__pyx_t_2 = ((__pyx_v_len_ != 0) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":613
+ /* "s3ql/deltadump.pyx":622
*
* if len_ != 0:
* uint64 = 0 # <<<<<<<<<<<<<<
@@ -6774,16 +6784,16 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
*/
__pyx_v_uint64 = 0;
- /* "s3ql/deltadump.pyx":614
+ /* "s3ql/deltadump.pyx":623
* if len_ != 0:
* uint64 = 0
* fread(&uint64, len_, fp) # <<<<<<<<<<<<<<
* uint64 = le64toh(uint64)
*
*/
- __pyx_t_1 = __pyx_f_4s3ql_9deltadump_fread((&__pyx_v_uint64), __pyx_v_len_, __pyx_v_fp); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 614; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __pyx_f_4s3ql_9deltadump_fread((&__pyx_v_uint64), __pyx_v_len_, __pyx_v_fp); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 623; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":615
+ /* "s3ql/deltadump.pyx":624
* uint64 = 0
* fread(&uint64, len_, fp)
* uint64 = le64toh(uint64) # <<<<<<<<<<<<<<
@@ -6795,7 +6805,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
}
__pyx_L5:;
- /* "s3ql/deltadump.pyx":617
+ /* "s3ql/deltadump.pyx":626
* uint64 = le64toh(uint64)
*
* if negative == 1: # <<<<<<<<<<<<<<
@@ -6805,7 +6815,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
__pyx_t_2 = ((__pyx_v_negative == 1) != 0);
if (__pyx_t_2) {
- /* "s3ql/deltadump.pyx":618
+ /* "s3ql/deltadump.pyx":627
*
* if negative == 1:
* out[0] = - < int64_t > uint64 # <<<<<<<<<<<<<<
@@ -6817,7 +6827,7 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
}
/*else*/ {
- /* "s3ql/deltadump.pyx":620
+ /* "s3ql/deltadump.pyx":629
* out[0] = - < int64_t > uint64
* else:
* out[0] = < int64_t > uint64 # <<<<<<<<<<<<<<
@@ -6828,16 +6838,15 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
}
__pyx_L6:;
- /* "s3ql/deltadump.pyx":622
+ /* "s3ql/deltadump.pyx":631
* out[0] = < int64_t > uint64
*
* return len_ + 1 # <<<<<<<<<<<<<<
- *
*/
__pyx_r = (__pyx_v_len_ + 1);
goto __pyx_L0;
- /* "s3ql/deltadump.pyx":581
+ /* "s3ql/deltadump.pyx":590
* return len_ + 1
*
* cdef inline int read_integer(int64_t * out, FILE * fp) except -1: # <<<<<<<<<<<<<<
@@ -6854,14 +6863,14 @@ static CYTHON_INLINE int __pyx_f_4s3ql_9deltadump_read_integer(int64_t *__pyx_v_
return __pyx_r;
}
-static struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *__pyx_freelist_4s3ql_9deltadump___pyx_scope_struct_1_load_table[8];
-static int __pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table = 0;
+static struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table *__pyx_freelist_4s3ql_9deltadump___pyx_scope_struct__dump_table[8];
+static int __pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table = 0;
-static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct_1_load_table(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
+static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct__dump_table(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
PyObject *o;
- if (likely((__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table > 0) & (t->tp_basicsize == sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table)))) {
- o = (PyObject*)__pyx_freelist_4s3ql_9deltadump___pyx_scope_struct_1_load_table[--__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table];
- memset(o, 0, sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table));
+ if (CYTHON_COMPILING_IN_CPYTHON && likely((__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table > 0) & (t->tp_basicsize == sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table)))) {
+ o = (PyObject*)__pyx_freelist_4s3ql_9deltadump___pyx_scope_struct__dump_table[--__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table];
+ memset(o, 0, sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table));
(void) PyObject_INIT(o, t);
} else {
o = (*t->tp_alloc)(t, 0);
@@ -6870,20 +6879,20 @@ static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct_1_load_table(P
return o;
}
-static void __pyx_tp_dealloc_4s3ql_9deltadump___pyx_scope_struct_1_load_table(PyObject *o) {
- if ((__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table < 8) & (Py_TYPE(o)->tp_basicsize == sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table))) {
- __pyx_freelist_4s3ql_9deltadump___pyx_scope_struct_1_load_table[__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table++] = ((struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *)o);
+static void __pyx_tp_dealloc_4s3ql_9deltadump___pyx_scope_struct__dump_table(PyObject *o) {
+ if (CYTHON_COMPILING_IN_CPYTHON && ((__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table < 8) & (Py_TYPE(o)->tp_basicsize == sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table)))) {
+ __pyx_freelist_4s3ql_9deltadump___pyx_scope_struct__dump_table[__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table++] = ((struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table *)o);
} else {
(*Py_TYPE(o)->tp_free)(o);
}
}
-static PyTypeObject __pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table = {
+static PyTypeObject __pyx_type_4s3ql_9deltadump___pyx_scope_struct__dump_table = {
PyVarObject_HEAD_INIT(0, 0)
- __Pyx_NAMESTR("s3ql.deltadump.__pyx_scope_struct_1_load_table"), /*tp_name*/
- sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table), /*tp_basicsize*/
+ __Pyx_NAMESTR("s3ql.deltadump.__pyx_scope_struct__dump_table"), /*tp_name*/
+ sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table), /*tp_basicsize*/
0, /*tp_itemsize*/
- __pyx_tp_dealloc_4s3ql_9deltadump___pyx_scope_struct_1_load_table, /*tp_dealloc*/
+ __pyx_tp_dealloc_4s3ql_9deltadump___pyx_scope_struct__dump_table, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
@@ -6920,7 +6929,7 @@ static PyTypeObject __pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
- __pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct_1_load_table, /*tp_new*/
+ __pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct__dump_table, /*tp_new*/
0, /*tp_free*/
0, /*tp_is_gc*/
0, /*tp_bases*/
@@ -6937,14 +6946,14 @@ static PyTypeObject __pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table
#endif
};
-static struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table *__pyx_freelist_4s3ql_9deltadump___pyx_scope_struct__dump_table[8];
-static int __pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table = 0;
+static struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *__pyx_freelist_4s3ql_9deltadump___pyx_scope_struct_1_load_table[8];
+static int __pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table = 0;
-static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct__dump_table(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
+static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct_1_load_table(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
PyObject *o;
- if (likely((__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table > 0) & (t->tp_basicsize == sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table)))) {
- o = (PyObject*)__pyx_freelist_4s3ql_9deltadump___pyx_scope_struct__dump_table[--__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table];
- memset(o, 0, sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table));
+ if (CYTHON_COMPILING_IN_CPYTHON && likely((__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table > 0) & (t->tp_basicsize == sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table)))) {
+ o = (PyObject*)__pyx_freelist_4s3ql_9deltadump___pyx_scope_struct_1_load_table[--__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table];
+ memset(o, 0, sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table));
(void) PyObject_INIT(o, t);
} else {
o = (*t->tp_alloc)(t, 0);
@@ -6953,20 +6962,20 @@ static PyObject *__pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct__dump_table(Py
return o;
}
-static void __pyx_tp_dealloc_4s3ql_9deltadump___pyx_scope_struct__dump_table(PyObject *o) {
- if ((__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table < 8) & (Py_TYPE(o)->tp_basicsize == sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table))) {
- __pyx_freelist_4s3ql_9deltadump___pyx_scope_struct__dump_table[__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct__dump_table++] = ((struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table *)o);
+static void __pyx_tp_dealloc_4s3ql_9deltadump___pyx_scope_struct_1_load_table(PyObject *o) {
+ if (CYTHON_COMPILING_IN_CPYTHON && ((__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table < 8) & (Py_TYPE(o)->tp_basicsize == sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table)))) {
+ __pyx_freelist_4s3ql_9deltadump___pyx_scope_struct_1_load_table[__pyx_freecount_4s3ql_9deltadump___pyx_scope_struct_1_load_table++] = ((struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table *)o);
} else {
(*Py_TYPE(o)->tp_free)(o);
}
}
-static PyTypeObject __pyx_type_4s3ql_9deltadump___pyx_scope_struct__dump_table = {
+static PyTypeObject __pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table = {
PyVarObject_HEAD_INIT(0, 0)
- __Pyx_NAMESTR("s3ql.deltadump.__pyx_scope_struct__dump_table"), /*tp_name*/
- sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct__dump_table), /*tp_basicsize*/
+ __Pyx_NAMESTR("s3ql.deltadump.__pyx_scope_struct_1_load_table"), /*tp_name*/
+ sizeof(struct __pyx_obj_4s3ql_9deltadump___pyx_scope_struct_1_load_table), /*tp_basicsize*/
0, /*tp_itemsize*/
- __pyx_tp_dealloc_4s3ql_9deltadump___pyx_scope_struct__dump_table, /*tp_dealloc*/
+ __pyx_tp_dealloc_4s3ql_9deltadump___pyx_scope_struct_1_load_table, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
@@ -7003,7 +7012,7 @@ static PyTypeObject __pyx_type_4s3ql_9deltadump___pyx_scope_struct__dump_table =
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
- __pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct__dump_table, /*tp_new*/
+ __pyx_tp_new_4s3ql_9deltadump___pyx_scope_struct_1_load_table, /*tp_new*/
0, /*tp_free*/
0, /*tp_is_gc*/
0, /*tp_bases*/
@@ -7108,7 +7117,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
{&__pyx_n_s_getLogger, __pyx_k_getLogger, sizeof(__pyx_k_getLogger), 0, 0, 1, 1},
{&__pyx_n_s_get_val, __pyx_k_get_val, sizeof(__pyx_k_get_val), 0, 0, 1, 1},
{&__pyx_n_s_getfilesystemencoding, __pyx_k_getfilesystemencoding, sizeof(__pyx_k_getfilesystemencoding), 0, 0, 1, 1},
- {&__pyx_kp_s_home_nikratio_in_progress_s3ql, __pyx_k_home_nikratio_in_progress_s3ql, sizeof(__pyx_k_home_nikratio_in_progress_s3ql), 0, 0, 1, 0},
+ {&__pyx_kp_s_home_nikratio_tmp_s3ql_src_s3ql, __pyx_k_home_nikratio_tmp_s3ql_src_s3ql, sizeof(__pyx_k_home_nikratio_tmp_s3ql_src_s3ql), 0, 0, 1, 0},
{&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1},
{&__pyx_n_s_idx, __pyx_k_idx, sizeof(__pyx_k_idx), 0, 0, 1, 1},
{&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1},
@@ -7151,9 +7160,9 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
static int __Pyx_InitCachedBuiltins(void) {
__pyx_builtin_OSError = __Pyx_GetBuiltinName(__pyx_n_s_OSError); if (!__pyx_builtin_OSError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__pyx_builtin_IOError = __Pyx_GetBuiltinName(__pyx_n_s_IOError); if (!__pyx_builtin_IOError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 255; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
return 0;
__pyx_L1_error:;
return -1;
@@ -7163,118 +7172,118 @@ static int __Pyx_InitCachedConstants(void) {
__Pyx_RefNannyDeclarations
__Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
- /* "s3ql/deltadump.pyx":258
+ /* "s3ql/deltadump.pyx":260
* apsw_sqlite_options = set(apsw.compile_options)
* s3ql_sqlite_options = set()
* for idx in itertools.count(0): # <<<<<<<<<<<<<<
* buf = sqlite3_compileoption_get(idx)
* if buf is NULL:
*/
- __pyx_tuple__2 = PyTuple_Pack(1, __pyx_int_0); if (unlikely(!__pyx_tuple__2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__2 = PyTuple_Pack(1, __pyx_int_0); if (unlikely(!__pyx_tuple__2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__2);
__Pyx_GIVEREF(__pyx_tuple__2);
- /* "s3ql/deltadump.pyx":310
+ /* "s3ql/deltadump.pyx":315
*
* if db.file == ':memory:':
* raise ValueError("Can't access in-memory databases") # <<<<<<<<<<<<<<
*
* with ExitStack() as cm:
*/
- __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_u_Can_t_access_in_memory_databases); if (unlikely(!__pyx_tuple__3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 310; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_u_Can_t_access_in_memory_databases); if (unlikely(!__pyx_tuple__3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__3);
__Pyx_GIVEREF(__pyx_tuple__3);
- /* "s3ql/deltadump.pyx":359
+ /* "s3ql/deltadump.pyx":364
* for i in range(col_count):
* if sqlite3_column_type(stmt, i) is SQLITE_NULL:
* raise ValueError("Can't dump NULL values") # <<<<<<<<<<<<<<
*
* if col_types[i] == _INTEGER:
*/
- __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_u_Can_t_dump_NULL_values); if (unlikely(!__pyx_tuple__5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_u_Can_t_dump_NULL_values); if (unlikely(!__pyx_tuple__5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__5);
__Pyx_GIVEREF(__pyx_tuple__5);
- /* "s3ql/deltadump.pyx":312
+ /* "s3ql/deltadump.pyx":317
* raise ValueError("Can't access in-memory databases")
*
* with ExitStack() as cm: # <<<<<<<<<<<<<<
* # Get SQLite connection
* log.debug('Opening connection to %s', db.file)
*/
- __pyx_tuple__6 = PyTuple_Pack(3, Py_None, Py_None, Py_None); if (unlikely(!__pyx_tuple__6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__6 = PyTuple_Pack(3, Py_None, Py_None, Py_None); if (unlikely(!__pyx_tuple__6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 317; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__6);
__Pyx_GIVEREF(__pyx_tuple__6);
- /* "s3ql/deltadump.pyx":417
+ /* "s3ql/deltadump.pyx":426
*
* if db.file == ':memory:':
* raise ValueError("Can't access in-memory databases") # <<<<<<<<<<<<<<
*
* with ExitStack() as cm:
*/
- __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_u_Can_t_access_in_memory_databases); if (unlikely(!__pyx_tuple__7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_u_Can_t_access_in_memory_databases); if (unlikely(!__pyx_tuple__7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__7);
__Pyx_GIVEREF(__pyx_tuple__7);
- /* "s3ql/deltadump.pyx":432
+ /* "s3ql/deltadump.pyx":441
*
* # Copy settings
* for pragma in ('synchronous', 'foreign_keys'): # <<<<<<<<<<<<<<
* val = db.get_val('PRAGMA %s' % pragma)
* cmd = ('PRAGMA %s = %s' % (pragma, val)).encode('utf-8')
*/
- __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_u_synchronous, __pyx_n_u_foreign_keys); if (unlikely(!__pyx_tuple__8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 432; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_u_synchronous, __pyx_n_u_foreign_keys); if (unlikely(!__pyx_tuple__8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__8);
__Pyx_GIVEREF(__pyx_tuple__8);
- /* "s3ql/deltadump.pyx":419
+ /* "s3ql/deltadump.pyx":428
* raise ValueError("Can't access in-memory databases")
*
* with ExitStack() as cm: # <<<<<<<<<<<<<<
* # Get SQLite connection
* log.debug('Opening connection to %s', db.file)
*/
- __pyx_tuple__10 = PyTuple_Pack(3, Py_None, Py_None, Py_None); if (unlikely(!__pyx_tuple__10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__10 = PyTuple_Pack(3, Py_None, Py_None, Py_None); if (unlikely(!__pyx_tuple__10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__10);
__Pyx_GIVEREF(__pyx_tuple__10);
- /* "s3ql/deltadump.pyx":232
+ /* "s3ql/deltadump.pyx":234
* return fp
*
* def check_sqlite(): # <<<<<<<<<<<<<<
* '''Check if deltadump and apsw module use compatible SQLite code.
*
*/
- __pyx_tuple__11 = PyTuple_Pack(6, __pyx_n_s_buf, __pyx_n_s_apsw_sqlite_version, __pyx_n_s_s3ql_sqlite_version, __pyx_n_s_apsw_sqlite_options, __pyx_n_s_s3ql_sqlite_options, __pyx_n_s_idx); if (unlikely(!__pyx_tuple__11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__11 = PyTuple_Pack(6, __pyx_n_s_buf, __pyx_n_s_apsw_sqlite_version, __pyx_n_s_s3ql_sqlite_version, __pyx_n_s_apsw_sqlite_options, __pyx_n_s_s3ql_sqlite_options, __pyx_n_s_idx); if (unlikely(!__pyx_tuple__11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__11);
__Pyx_GIVEREF(__pyx_tuple__11);
- __pyx_codeobj__12 = (PyObject*)__Pyx_PyCode_New(0, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__11, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_nikratio_in_progress_s3ql, __pyx_n_s_check_sqlite, 232, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_codeobj__12 = (PyObject*)__Pyx_PyCode_New(0, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__11, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_nikratio_tmp_s3ql_src_s3ql, __pyx_n_s_check_sqlite, 234, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__12)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":275
+ /* "s3ql/deltadump.pyx":277
* s3ql_sqlite_options - apsw_sqlite_options))
*
* def dump_table(table, order, columns, db, fh): # <<<<<<<<<<<<<<
* '''Dump *columns* of *table* into *fh*
*
*/
- __pyx_tuple__13 = PyTuple_Pack(23, __pyx_n_s_table, __pyx_n_s_order, __pyx_n_s_columns, __pyx_n_s_db, __pyx_n_s_fh, __pyx_n_s_sqlite3_db, __pyx_n_s_stmt, __pyx_n_s_col_types, __pyx_n_s_col_args, __pyx_n_s_col_count, __pyx_n_s_rc, __pyx_n_s_i, __pyx_n_s_len, __pyx_n_s_int64_prev, __pyx_n_s_int64, __pyx_n_s_tmp, __pyx_n_s_fp, __pyx_n_s_buf, __pyx_n_s_row_count, __pyx_n_s_cm, __pyx_n_s_dbfile_b, __pyx_n_s_col_names, __pyx_n_s_query); if (unlikely(!__pyx_tuple__13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__13 = PyTuple_Pack(23, __pyx_n_s_table, __pyx_n_s_order, __pyx_n_s_columns, __pyx_n_s_db, __pyx_n_s_fh, __pyx_n_s_sqlite3_db, __pyx_n_s_stmt, __pyx_n_s_col_types, __pyx_n_s_col_args, __pyx_n_s_col_count, __pyx_n_s_rc, __pyx_n_s_i, __pyx_n_s_len, __pyx_n_s_int64_prev, __pyx_n_s_int64, __pyx_n_s_tmp, __pyx_n_s_fp, __pyx_n_s_buf, __pyx_n_s_row_count, __pyx_n_s_cm, __pyx_n_s_dbfile_b, __pyx_n_s_col_names, __pyx_n_s_query); if (unlikely(!__pyx_tuple__13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__13);
__Pyx_GIVEREF(__pyx_tuple__13);
- __pyx_codeobj__14 = (PyObject*)__Pyx_PyCode_New(5, 0, 23, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__13, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_nikratio_in_progress_s3ql, __pyx_n_s_dump_table, 275, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_codeobj__14 = (PyObject*)__Pyx_PyCode_New(5, 0, 23, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__13, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_nikratio_tmp_s3ql_src_s3ql, __pyx_n_s_dump_table, 277, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- /* "s3ql/deltadump.pyx":390
+ /* "s3ql/deltadump.pyx":395
* fwrite(buf, len_, fp)
*
* def load_table(table, columns, db, fh, trx_rows=5000): # <<<<<<<<<<<<<<
* '''Load *columns* of *table* from *fh*
*
*/
- __pyx_tuple__15 = PyTuple_Pack(28, __pyx_n_s_table, __pyx_n_s_columns, __pyx_n_s_db, __pyx_n_s_fh, __pyx_n_s_trx_rows, __pyx_n_s_sqlite3_db, __pyx_n_s_stmt, __pyx_n_s_begin_stmt, __pyx_n_s_commit_stmt, __pyx_n_s_col_types, __pyx_n_s_col_args, __pyx_n_s_col_count, __pyx_n_s_rc, __pyx_n_s_len, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_int64_prev, __pyx_n_s_fp, __pyx_n_s_buf, __pyx_n_s_row_count, __pyx_n_s_int64, __pyx_n_s_cm, __pyx_n_s_dbfile_b, __pyx_n_s_pragma, __pyx_n_s_val, __pyx_n_s_cmd, __pyx_n_s_col_names, __pyx_n_s_query); if (unlikely(!__pyx_tuple__15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_tuple__15 = PyTuple_Pack(28, __pyx_n_s_table, __pyx_n_s_columns, __pyx_n_s_db, __pyx_n_s_fh, __pyx_n_s_trx_rows, __pyx_n_s_sqlite3_db, __pyx_n_s_stmt, __pyx_n_s_begin_stmt, __pyx_n_s_commit_stmt, __pyx_n_s_col_types, __pyx_n_s_col_args, __pyx_n_s_col_count, __pyx_n_s_rc, __pyx_n_s_len, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_int64_prev, __pyx_n_s_fp, __pyx_n_s_buf, __pyx_n_s_row_count, __pyx_n_s_int64, __pyx_n_s_cm, __pyx_n_s_dbfile_b, __pyx_n_s_pragma, __pyx_n_s_val, __pyx_n_s_cmd, __pyx_n_s_col_names, __pyx_n_s_query); if (unlikely(!__pyx_tuple__15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_tuple__15);
__Pyx_GIVEREF(__pyx_tuple__15);
- __pyx_codeobj__16 = (PyObject*)__Pyx_PyCode_New(5, 0, 28, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__15, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_nikratio_in_progress_s3ql, __pyx_n_s_load_table, 390, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__16)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_codeobj__16 = (PyObject*)__Pyx_PyCode_New(5, 0, 28, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__15, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_nikratio_tmp_s3ql_src_s3ql, __pyx_n_s_load_table, 395, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__16)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_RefNannyFinishContext();
return 0;
__pyx_L1_error:;
@@ -7374,12 +7383,12 @@ PyMODINIT_FUNC PyInit_deltadump(void)
/*--- Variable export code ---*/
/*--- Function export code ---*/
/*--- Type init code ---*/
- if (PyType_Ready(&__pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
- __pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table.tp_print = 0;
- __pyx_ptype_4s3ql_9deltadump___pyx_scope_struct_1_load_table = &__pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table;
- if (PyType_Ready(&__pyx_type_4s3ql_9deltadump___pyx_scope_struct__dump_table) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ if (PyType_Ready(&__pyx_type_4s3ql_9deltadump___pyx_scope_struct__dump_table) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__pyx_type_4s3ql_9deltadump___pyx_scope_struct__dump_table.tp_print = 0;
__pyx_ptype_4s3ql_9deltadump___pyx_scope_struct__dump_table = &__pyx_type_4s3ql_9deltadump___pyx_scope_struct__dump_table;
+ if (PyType_Ready(&__pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table.tp_print = 0;
+ __pyx_ptype_4s3ql_9deltadump___pyx_scope_struct_1_load_table = &__pyx_type_4s3ql_9deltadump___pyx_scope_struct_1_load_table;
/*--- Type import code ---*/
/*--- Variable import code ---*/
/*--- Function import code ---*/
@@ -7494,7 +7503,7 @@ PyMODINIT_FUNC PyInit_deltadump(void)
PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
__Pyx_GIVEREF(__pyx_t_1);
__pyx_t_1 = 0;
- __pyx_t_1 = PyObject_Call(__pyx_t_2, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
__Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
__Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -7629,40 +7638,40 @@ PyMODINIT_FUNC PyInit_deltadump(void)
__pyx_k_ = __pyx_builtin_OSError;
__Pyx_GIVEREF(__pyx_builtin_OSError);
- /* "s3ql/deltadump.pyx":232
+ /* "s3ql/deltadump.pyx":234
* return fp
*
* def check_sqlite(): # <<<<<<<<<<<<<<
* '''Check if deltadump and apsw module use compatible SQLite code.
*
*/
- __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_1check_sqlite, NULL, __pyx_n_s_s3ql_deltadump); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_1check_sqlite, NULL, __pyx_n_s_s3ql_deltadump); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- if (PyDict_SetItem(__pyx_d, __pyx_n_s_check_sqlite, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ if (PyDict_SetItem(__pyx_d, __pyx_n_s_check_sqlite, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":275
+ /* "s3ql/deltadump.pyx":277
* s3ql_sqlite_options - apsw_sqlite_options))
*
* def dump_table(table, order, columns, db, fh): # <<<<<<<<<<<<<<
* '''Dump *columns* of *table* into *fh*
*
*/
- __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_3dump_table, NULL, __pyx_n_s_s3ql_deltadump); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_3dump_table, NULL, __pyx_n_s_s3ql_deltadump); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- if (PyDict_SetItem(__pyx_d, __pyx_n_s_dump_table, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ if (PyDict_SetItem(__pyx_d, __pyx_n_s_dump_table, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
- /* "s3ql/deltadump.pyx":390
+ /* "s3ql/deltadump.pyx":395
* fwrite(buf, len_, fp)
*
* def load_table(table, columns, db, fh, trx_rows=5000): # <<<<<<<<<<<<<<
* '''Load *columns* of *table* from *fh*
*
*/
- __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_5load_table, NULL, __pyx_n_s_s3ql_deltadump); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_4s3ql_9deltadump_5load_table, NULL, __pyx_n_s_s3ql_deltadump); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_GOTREF(__pyx_t_1);
- if (PyDict_SetItem(__pyx_d, __pyx_n_s_load_table, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+ if (PyDict_SetItem(__pyx_d, __pyx_n_s_load_table, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
/* "s3ql/deltadump.pyx":1
@@ -7724,6 +7733,29 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
return result;
}
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) {
+ PyObject *result;
+ ternaryfunc call = func->ob_type->tp_call;
+ if (unlikely(!call))
+ return PyObject_Call(func, arg, kw);
+#if PY_VERSION_HEX >= 0x02060000
+ if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object")))
+ return NULL;
+#endif
+ result = (*call)(func, arg, kw);
+#if PY_VERSION_HEX >= 0x02060000
+ Py_LeaveRecursiveCall();
+#endif
+ if (unlikely(!result) && unlikely(!PyErr_Occurred())) {
+ PyErr_SetString(
+ PyExc_SystemError,
+ "NULL result without error in PyObject_Call");
+ }
+ return result;
+}
+#endif
+
static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
#if CYTHON_COMPILING_IN_CPYTHON
PyObject *tmp_type, *tmp_value, *tmp_tb;
@@ -9768,7 +9800,7 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
return 0;
}
-static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char* c_str) {
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) {
return __Pyx_PyUnicode_FromStringAndSize(c_str, strlen(c_str));
}
static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
@@ -9805,7 +9837,7 @@ static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_
if (PyUnicode_READY(o) == -1) return NULL;
#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
if (PyUnicode_IS_ASCII(o)) {
- *length = PyUnicode_GET_DATA_SIZE(o);
+ *length = PyUnicode_GET_LENGTH(o);
return PyUnicode_AsUTF8(o);
} else {
PyUnicode_AsASCIIString(o);
@@ -9817,12 +9849,14 @@ static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_
#endif /* PY_VERSION_HEX < 0x03030000 */
} else
#endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT */
+#if !CYTHON_COMPILING_IN_PYPY
#if PY_VERSION_HEX >= 0x02060000
if (PyByteArray_Check(o)) {
*length = PyByteArray_GET_SIZE(o);
return PyByteArray_AS_STRING(o);
} else
#endif
+#endif
{
char* result;
int r = PyBytes_AsStringAndSize(o, &result, length);
diff --git a/src/s3ql/deltadump.pyx b/src/s3ql/deltadump.pyx
index b86ea4e..d58f0d9 100644
--- a/src/s3ql/deltadump.pyx
+++ b/src/s3ql/deltadump.pyx
@@ -136,7 +136,7 @@ cdef int raise_from_errno(err_class=OSError) except -1:
'''Raise OSError for current errno value'''
raise err_class(errno, PyUnicode_FromString(strerror(errno)))
-
+
cdef int fclose(FILE * fp) except -1:
'''Call libc.fclose() and raise exception on failure'''
@@ -147,7 +147,7 @@ cdef int fclose(FILE * fp) except -1:
# below (which is necessary in case there is cached input data)
if fflush(fp) != 0:
raise_from_errno()
-
+
# Reposition FD to position of FILE*, otherwise next read from FD will miss
# data currently in stream buffer. It seems that call to fflush() achieves
# the same thing, but this does not seem to be documented so we don't rely
@@ -179,7 +179,7 @@ cdef void * calloc(size_t cnt, size_t size) except NULL:
cdef int SQLITE_CHECK_RC(int rc, int success, sqlite3* db) except -1:
'''Raise correct exception if *rc* != *success*'''
-
+
if rc != success:
exc = apsw.exceptionfor(rc)
raise type(exc)(PyUnicode_FromString(sqlite3_errmsg(db)))
@@ -193,13 +193,15 @@ cdef int prep_columns(columns, int** col_types_p, int** col_args_p) except -1:
Both arrays are allocated dynamically, caller has to ensure
that they're freed again.
'''
- cdef int col_count, *col_types, *col_args
-
+ cdef int col_count
+ cdef int *col_types
+ cdef int *col_args
+
col_count = len(columns)
col_types = < int *> calloc(col_count, sizeof(int))
col_args = < int *> calloc(col_count, sizeof(int))
- # Initialize col_args and col_types
+ # Initialize col_args and col_types
for i in range(col_count):
if columns[i][1] not in (BLOB, INTEGER, TIME):
raise ValueError("Invalid type for column %d" % i)
@@ -240,7 +242,7 @@ def check_sqlite():
same options can the database object be shared between *apsw* and
*deltadump*.
'''
-
+
cdef const_char *buf
apsw_sqlite_version = apsw.sqlitelibversion()
@@ -252,7 +254,7 @@ def check_sqlite():
if apsw_sqlite_version != s3ql_sqlite_version:
raise RuntimeError('SQLite version mismatch between APSW and S3QL '
'(%s vs %s)' % (apsw_sqlite_version, s3ql_sqlite_version))
-
+
apsw_sqlite_options = set(apsw.compile_options)
s3ql_sqlite_options = set()
for idx in itertools.count(0):
@@ -278,14 +280,14 @@ def dump_table(table, order, columns, db, fh):
*order* specifies the order in which the rows are written and must be a
string that can be inserted after the "ORDER BY" clause in an SQL SELECT
statement.
-
+
*db* is an `s3ql.Connection` instance for the database.
-
+
*columns* must a list of 3-tuples, one for each column that should be
stored. The first element of the tuple must contain the column name and the
second element the type of data stored in the column (`INTEGER`, `TIME`
or `BLOB`). Times will be converted to nanosecond integers.
-
+
For integers and seconds, the third tuple element specifies the expected
change of the values between rows. For blobs it can be either zero
(indicating variable length columns) or an integer specifying the length of
@@ -300,8 +302,11 @@ def dump_table(table, order, columns, db, fh):
cdef sqlite3 *sqlite3_db
cdef sqlite3_stmt *stmt
- cdef int *col_types, *col_args, col_count, rc, i, len_
- cdef int64_t *int64_prev, int64, tmp
+ cdef int *col_types
+ cdef int *col_args
+ cdef int col_count, rc, i, len_
+ cdef int64_t *int64_prev
+ cdef int64_t int64, tmp
cdef FILE *fp
cdef const_void *buf
cdef int64_t row_count
@@ -325,11 +330,11 @@ def dump_table(table, order, columns, db, fh):
fp = dup_to_fp(fh, b'wb')
cm.callback(lambda: fclose(fp))
- # Allocate col_args and col_types
+ # Allocate col_args and col_types
col_count = prep_columns(columns, &col_types, &col_args)
cm.callback(lambda: free(col_args))
cm.callback(lambda: free(col_types))
-
+
# Allocate int64_prev
int64_prev = < int64_t *> calloc(len(columns), sizeof(int64_t))
cm.callback(lambda: free(int64_prev))
@@ -391,7 +396,7 @@ def load_table(table, columns, db, fh, trx_rows=5000):
'''Load *columns* of *table* from *fh*
*db* is an `s3ql.Connection` instance for the database.
-
+
*columns* must be the same list of 3-tuples that was passed to
`dump_table` when creating the dump stored in *fh*.
@@ -406,8 +411,12 @@ def load_table(table, columns, db, fh, trx_rows=5000):
'''
cdef sqlite3 *sqlite3_db
- cdef sqlite3_stmt *stmt, *begin_stmt, *commit_stmt
- cdef int *col_types, *col_args, col_count, rc, len_, i, j
+ cdef sqlite3_stmt *stmt
+ cdef sqlite3_stmt *begin_stmt
+ cdef sqlite3_stmt *commit_stmt
+ cdef int *col_types
+ cdef int *col_args
+ cdef int col_count, rc, len_, i, j
cdef int64_t *int64_prev
cdef FILE *fp
cdef void *buf
@@ -446,7 +455,7 @@ def load_table(table, columns, db, fh, trx_rows=5000):
fp = dup_to_fp(fh, b'rb')
cm.callback(lambda: fclose(fp))
- # Allocate col_args and col_types
+ # Allocate col_args and col_types
col_count = prep_columns(columns, &col_types, &col_args)
cm.callback(lambda: free(col_args))
cm.callback(lambda: free(col_types))
@@ -520,10 +529,10 @@ def load_table(table, columns, db, fh, trx_rows=5000):
if len_ != 0:
fread(buf, len_, fp)
-
+
SQLITE_CHECK_RC(sqlite3_bind_blob(stmt, j + 1, buf, len_, SQLITE_TRANSIENT),
SQLITE_OK, sqlite3_db)
-
+
SQLITE_CHECK_RC(sqlite3_step(stmt), SQLITE_DONE, sqlite3_db)
SQLITE_CHECK_RC(sqlite3_reset(stmt), SQLITE_OK, sqlite3_db)
@@ -536,7 +545,7 @@ def load_table(table, columns, db, fh, trx_rows=5000):
SQLITE_CHECK_RC(sqlite3_step(begin_stmt), SQLITE_DONE, sqlite3_db)
SQLITE_CHECK_RC(sqlite3_reset(commit_stmt), SQLITE_OK, sqlite3_db)
SQLITE_CHECK_RC(sqlite3_reset(begin_stmt), SQLITE_OK, sqlite3_db)
-
+
cdef inline int write_integer(int64_t int64, FILE * fp) except -1:
'''Write *int64* into *fp*, using as little space as possible
@@ -620,4 +629,3 @@ cdef inline int read_integer(int64_t * out, FILE * fp) except -1:
out[0] = < int64_t > uint64
return len_ + 1
-
diff --git a/src/s3ql/exit_stack.py b/src/s3ql/exit_stack.py
index 56b0398..2d63159 100644
--- a/src/s3ql/exit_stack.py
+++ b/src/s3ql/exit_stack.py
@@ -25,7 +25,7 @@ if sys.version_info < (3,3):
if sys.version_info >= (3,3,3):
ExitStack = _ExitStack
-else:
+else:
class ExitStack(_ExitStack):
def __exit__(self, *exc_details):
received_exc = exc_details[0] is not None
@@ -68,5 +68,3 @@ else:
exc_details[1].__context__ = fixed_ctx
raise
return received_exc and suppressed_exc
-
-
diff --git a/src/s3ql/fs.py b/src/s3ql/fs.py
index 836a04d..6166c5a 100644
--- a/src/s3ql/fs.py
+++ b/src/s3ql/fs.py
@@ -64,13 +64,13 @@ class Operations(llfuse.Operations):
This class implements low-level FUSE operations and is meant to be passed to
llfuse.init().
-
+
The ``access`` method of this class always gives full access, independent of
file permissions. If the FUSE library is initialized with ``allow_other`` or
``allow_root``, the ``default_permissions`` option should therefore always
be passed as well.
-
-
+
+
Attributes:
-----------
@@ -85,17 +85,17 @@ class Operations(llfuse.Operations):
attempts to retrieve them. This attribute is a dict (indexed by inodes)
of sets of block indices. Broken blocks are removed from the cache
when an inode is forgotten.
-
+
Multithreading
--------------
-
+
All methods are reentrant and may release the global lock while they
are running.
-
-
+
+
Directory Entry Types
----------------------
-
+
S3QL is quite agnostic when it comes to directory entry types. Every
directory entry can contain other entries *and* have a associated data,
size, link target and device number. However, S3QL makes some provisions for
@@ -115,7 +115,7 @@ class Operations(llfuse.Operations):
self.cache = block_cache
self.failsafe = False
self.broken_blocks = collections.defaultdict(set)
-
+
# Root inode is always open
self.open_inodes[llfuse.ROOT_INODE] += 1
@@ -198,7 +198,7 @@ class Operations(llfuse.Operations):
inode.atime = time.time()
with self.db.query("SELECT name_id, name, inode FROM contents_v "
- 'WHERE parent_inode=? AND name_id > ? ORDER BY name_id',
+ 'WHERE parent_inode=? AND name_id > ? ORDER BY name_id',
(id_, off)) as res:
for (next_, name, cid_) in res:
yield (name, self.inodes[cid_], next_)
@@ -214,7 +214,7 @@ class Operations(llfuse.Operations):
return self.extstat()
raise llfuse.FUSEError(errno.EINVAL)
-
+
# http://code.google.com/p/s3ql/issues/detail?id=385
elif name in (b'system.posix_acl_access',
b'system.posix_acl_default'):
@@ -260,12 +260,12 @@ class Operations(llfuse.Operations):
self.cache.max_size = pickle.loads(value)
else:
raise llfuse.FUSEError(errno.EINVAL)
-
+
# http://code.google.com/p/s3ql/issues/detail?id=385
elif name in (b'system.posix_acl_access',
b'system.posix_acl_default'):
raise FUSEError(ACL_ERRNO)
-
+
else:
if self.failsafe or self.inodes[id_].locked:
raise FUSEError(errno.EPERM)
@@ -300,7 +300,7 @@ class Operations(llfuse.Operations):
if self.failsafe:
raise FUSEError(errno.EPERM)
-
+
log.debug('lock_tree(%d): start', id0)
queue = [ id0 ]
self.inodes[id0].locked = True
@@ -314,7 +314,7 @@ class Operations(llfuse.Operations):
for (id_,) in res:
self.inodes[id_].locked = True
processed += 1
-
+
if self.db.has_val('SELECT 1 FROM contents WHERE parent_inode=?', (id_,)):
queue.append(id_)
@@ -356,11 +356,11 @@ class Operations(llfuse.Operations):
inval_entry = lambda x: llfuse.invalidate_entry(id_p, x)
else:
inval_entry = lambda x: None
-
+
with self.db.query('SELECT name_id, inode FROM contents WHERE '
'parent_inode=?', (id_p,)) as res:
for (name_id, id_) in res:
-
+
if self.db.has_val('SELECT 1 FROM contents WHERE parent_inode=?', (id_,)):
if not found_subdirs:
# When current directory has subdirectories, we must reinsert
@@ -368,16 +368,16 @@ class Operations(llfuse.Operations):
found_subdirs = True
queue.append(id_p)
queue.append(id_)
-
+
else:
name = self.db.get_val("SELECT name FROM names WHERE id=?", (name_id,))
inval_entry(name)
self._remove(id_p, name, id_, force=True)
-
+
processed += 1
if processed > gil_step:
# Also reinsert current directory if we need to yield to other threads
- if not found_subdirs:
+ if not found_subdirs:
queue.append(id_p)
break
@@ -391,10 +391,10 @@ class Operations(llfuse.Operations):
log.debug('remove_tree(%d, %s): re-acquired lock', id_p0, name0)
stamp = time.time()
-
+
if id_p0 in self.open_inodes:
log.debug('remove_tree(%d, %s): invalidate_entry(%d, %r)',
- id_p0, name0, id_p0, name0)
+ id_p0, name0, id_p0, name0)
llfuse.invalidate_entry(id_p0, name0)
self._remove(id_p0, name0, id0, force=True)
@@ -447,10 +447,10 @@ class Operations(llfuse.Operations):
with db.query('SELECT name_id, inode FROM contents WHERE parent_inode=? '
'AND name_id > ? ORDER BY name_id', (src_id, off)) as res:
for (name_id, id_) in res:
-
+
if id_ not in id_cache:
inode = self.inodes[id_]
-
+
try:
inode_new = make_inode(refcount=1, mode=inode.mode, size=inode.size,
uid=inode.uid, gid=inode.gid,
@@ -459,23 +459,23 @@ class Operations(llfuse.Operations):
except OutOfInodesError:
log.warning('Could not find a free inode')
raise FUSEError(errno.ENOSPC)
-
+
id_new = inode_new.id
-
+
if inode.refcount != 1:
id_cache[id_] = id_new
-
+
db.execute('INSERT INTO symlink_targets (inode, target) '
'SELECT ?, target FROM symlink_targets WHERE inode=?',
(id_new, id_))
-
+
db.execute('INSERT INTO ext_attributes (inode, name_id, value) '
'SELECT ?, name_id, value FROM ext_attributes WHERE inode=?',
(id_new, id_))
db.execute('UPDATE names SET refcount = refcount + 1 WHERE '
'id IN (SELECT name_id FROM ext_attributes WHERE inode=?)',
(id_,))
-
+
processed += db.execute('INSERT INTO inode_blocks (inode, blockno, block_id) '
'SELECT ?, blockno, block_id FROM inode_blocks '
'WHERE inode=?', (id_new, id_))
@@ -483,19 +483,19 @@ class Operations(llfuse.Operations):
'SELECT id, hash, refcount+COUNT(id), size, obj_id '
'FROM inode_blocks JOIN blocks ON block_id = id '
'WHERE inode = ? GROUP BY id', (id_new,))
-
+
if db.has_val('SELECT 1 FROM contents WHERE parent_inode=?', (id_,)):
queue.append((id_, id_new, 0))
else:
id_new = id_cache[id_]
self.inodes[id_new].refcount += 1
-
+
db.execute('INSERT INTO contents (name_id, inode, parent_inode) VALUES(?, ?, ?)',
(name_id, id_new, target_id))
db.execute('UPDATE names SET refcount=refcount+1 WHERE id=?', (name_id,))
-
+
processed += 1
-
+
if processed > gil_step:
log.debug('copy_tree(%d, %d): Requeueing (%d, %d, %d) to yield lock',
src_inode.id, target_inode.id, src_id, target_id, name_id)
@@ -525,7 +525,7 @@ class Operations(llfuse.Operations):
log.debug('unlink(%d, %r): start', id_p, name)
if self.failsafe:
raise FUSEError(errno.EPERM)
-
+
inode = self.lookup(id_p, name)
if stat.S_ISDIR(inode.mode):
@@ -539,7 +539,7 @@ class Operations(llfuse.Operations):
log.debug('rmdir(%d, %r): start', id_p, name)
if self.failsafe:
raise FUSEError(errno.EPERM)
-
+
inode = self.lookup(id_p, name)
if self.inodes[id_p].locked:
@@ -553,11 +553,11 @@ class Operations(llfuse.Operations):
self.forget([(inode.id, 1)])
def _remove(self, id_p, name, id_, force=False):
- '''Remove entry `name` with parent inode `id_p`
-
+ '''Remove entry `name` with parent inode `id_p`
+
`id_` must be the inode of `name`. If `force` is True, then
the `locked` attribute is ignored.
-
+
This method releases the global lock.
'''
@@ -625,7 +625,7 @@ class Operations(llfuse.Operations):
return inode
def rename(self, id_p_old, name_old, id_p_new, name_new):
- log.debug('rename(%d, %r, %d, %r): start', id_p_old, name_old, id_p_new, name_new)
+ log.debug('rename(%d, %r, %d, %r): start', id_p_old, name_old, id_p_new, name_new)
if name_new == CTRL_NAME or name_old == CTRL_NAME:
log.warning('Attempted to rename s3ql control file (%s -> %s)',
get_path(id_p_old, self.db, name_old),
@@ -659,7 +659,7 @@ class Operations(llfuse.Operations):
def _add_name(self, name):
'''Get id for *name* and increase refcount
-
+
Name is inserted in table if it does not yet exist.
'''
@@ -674,7 +674,7 @@ class Operations(llfuse.Operations):
def _del_name(self, name):
'''Decrease refcount for *name*
-
+
Name is removed from table if refcount drops to zero. Returns the
(possibly former) id of the name.
'''
@@ -786,7 +786,7 @@ class Operations(llfuse.Operations):
"""Handles FUSE setattr() requests"""
if log.isEnabledFor(logging.DEBUG):
log.debug('setattr(%d, %s): start', id_,
- ', '.join('%s=%r' % (x, getattr(attr, x))
+ ', '.join('%s=%r' % (x, getattr(attr, x))
for x in dir(attr)
if x.startswith('st_') and getattr(attr, x) is not None ))
@@ -807,7 +807,7 @@ class Operations(llfuse.Operations):
# Adjust file size
inode.size = len_
- # Delete blocks and truncate last one if required
+ # Delete blocks and truncate last one if required
if cutoff == 0:
self.cache.remove(id_, last_block, total_blocks)
else:
@@ -904,15 +904,15 @@ class Operations(llfuse.Operations):
# be allocated. This doesn't make much sense for S3QL, so we just
# return the average size of stored blocks.
stat_.f_frsize = max(4096, size // blocks) if blocks != 0 else 4096
-
+
# This should actually be the "preferred block size for doing IO. However, `df` incorrectly
# interprets f_blocks, f_bfree and f_bavail in terms of f_bsize rather than f_frsize as it
# should (according to statvfs(3)), so the only way to return correct values *and* have df
# print something sensible is to set f_bsize and f_frsize to the same value. (cf.
# http://bugs.debian.org/671490)
- stat_.f_bsize = stat_.f_frsize
-
- # size of fs in f_frsize units. Since backend is supposed to be unlimited,
+ stat_.f_bsize = stat_.f_frsize
+
+ # size of fs in f_frsize units. Since backend is supposed to be unlimited,
# always return a half-full filesystem, but at least 1 TB)
fs_size = max(2 * size, 1024 ** 4)
@@ -937,7 +937,7 @@ class Operations(llfuse.Operations):
def access(self, id_, mode, ctx):
'''Check if requesting process has `mode` rights on `inode`.
-
+
This method always returns true, since it should only be called
when permission checking is disabled (if permission checking is
enabled, the `default_permissions` FUSE option should be set).
@@ -952,7 +952,7 @@ class Operations(llfuse.Operations):
log.debug('create(id_p=%d, %s): started', id_p, name)
if self.failsafe:
raise FUSEError(errno.EPERM)
-
+
try:
id_ = self.db.get_val("SELECT inode FROM contents_v WHERE name=? AND parent_inode=?",
(name, id_p))
@@ -1000,9 +1000,9 @@ class Operations(llfuse.Operations):
def read(self, fh, offset, length):
'''Read `size` bytes from `fh` at position `off`
-
- Unless EOF is reached, returns exactly `size` bytes.
-
+
+ Unless EOF is reached, returns exactly `size` bytes.
+
This method releases the global lock while it is running.
'''
log.debug('read(%d, %d, %d): start', fh, offset, length)
@@ -1021,7 +1021,7 @@ class Operations(llfuse.Operations):
length -= len(tmp)
offset += len(tmp)
- # Inode may have expired from cache
+ # Inode may have expired from cache
inode = self.inodes[fh]
if inode.atime < inode.ctime or inode.atime < inode.mtime:
@@ -1029,10 +1029,10 @@ class Operations(llfuse.Operations):
return buf.getvalue()
-
+
def write(self, fh, offset, buf):
'''Handle FUSE write requests.
-
+
This method releases the global lock while it is running.
'''
log.debug('write(%d, %d, datalen=%d): start', fh, offset, len(buf))
@@ -1064,12 +1064,12 @@ class Operations(llfuse.Operations):
"""Read or write as much as we can.
If *buf* is None, read and return up to *length* bytes.
-
+
If *length* is None, write from *buf* and return the number of
bytes written.
-
+
This is one method to reduce code duplication.
-
+
This method releases the global lock while it is running.
"""
@@ -1079,7 +1079,7 @@ class Operations(llfuse.Operations):
if id_ in self.broken_blocks and blockno in self.broken_blocks[id_]:
raise FUSEError(errno.EIO)
-
+
if length is None:
write = True
length = len(buf)
@@ -1087,11 +1087,11 @@ class Operations(llfuse.Operations):
write = False
else:
raise TypeError("Don't know what to do!")
-
+
# Don't try to write/read into the next block
if offset_rel + length > self.max_obj_size:
length = self.max_obj_size - offset_rel
-
+
try:
with self.cache.get(id_, blockno) as fh:
fh.seek(offset_rel)
@@ -1099,7 +1099,7 @@ class Operations(llfuse.Operations):
fh.write(buf[:length])
else:
buf = fh.read(length)
-
+
except NoSuchObject as exc:
log.error('Backend lost block %d of inode %d (id %s)!',
blockno, id_, exc.key)
@@ -1121,7 +1121,7 @@ class Operations(llfuse.Operations):
else:
# If we can't read enough, add null bytes
return buf + b"\0" * (length - len(buf))
-
+
def fsync(self, fh, datasync):
log.debug('fsync(%d, %s): start', fh, datasync)
if not datasync:
@@ -1172,7 +1172,7 @@ class Operations(llfuse.Operations):
def flush(self, fh):
log.debug('flush(%d): start', fh)
-
+
def update_logging(level, modules):
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
diff --git a/src/s3ql/fsck.py b/src/s3ql/fsck.py
index cbd6597..d74173e 100644
--- a/src/s3ql/fsck.py
+++ b/src/s3ql/fsck.py
@@ -8,9 +8,10 @@ This program can be distributed under the terms of the GNU GPLv3.
from .logging import logging, setup_logging, QuietError
from . import CURRENT_FS_REV
-from .backends.common import NoSuchObject, get_backend, DanglingStorageURLError
-from .common import (ROOT_INODE, inode_for_path, sha256_fh, get_path, BUFSIZE, get_backend_cachedir,
- get_seq_no, stream_write_bz2, stream_read_bz2, CTRL_INODE,
+from .backends.common import NoSuchObject, DanglingStorageURLError
+from .backends import get_backend
+from .common import (ROOT_INODE, inode_for_path, sha256_fh, get_path, BUFSIZE, get_backend_cachedir,
+ get_seq_no, stream_write_bz2, stream_read_bz2, CTRL_INODE,
PICKLE_PROTOCOL, is_mounted)
from .database import NoSuchRowError, Connection
from .metadata import restore_metadata, cycle_metadata, dump_metadata, create_tables
@@ -59,7 +60,7 @@ class Fsck(object):
def check(self):
"""Check file system
-
+
Sets instance variable `found_errors`.
"""
@@ -115,11 +116,11 @@ class Fsck(object):
def check_foreign_keys(self):
'''Check for referential integrity
-
+
Checks that all foreign keys in the SQLite tables actually resolve.
- This is necessary, because we disable runtime checking by SQLite
+ This is necessary, because we disable runtime checking by SQLite
for performance reasons.
-
+
Note: any problems should have already been caught by the more
specific checkers.
'''
@@ -200,7 +201,7 @@ class Fsck(object):
(block_id, inode, blockno))
# We just decrease the refcount, but don't take any action
- # because the reference count might be wrong
+ # because the reference count might be wrong
self.conn.execute('UPDATE blocks SET refcount=refcount-1 WHERE id=?', (old_block_id,))
self.unlinked_blocks.add(old_block_id)
@@ -276,7 +277,7 @@ class Fsck(object):
'ON parent_inode = inodes.id WHERE inodes.id IS NULL'):
self.found_errors = True
name = self.conn.get_val('SELECT name FROM names WHERE id = ?', (name_id,))
- (id_p_new, newname) = self.resolve_free(b"/lost+found",
+ (id_p_new, newname) = self.resolve_free(b"/lost+found",
('[%d]-%s' % (inode_p, name)).encode())
self.log_error('Parent inode %d for "%s" vanished, moving to /lost+found', inode_p, name)
@@ -417,13 +418,13 @@ class Fsck(object):
'(id INTEGER PRIMARY KEY, min_size INTEGER NOT NULL)')
try:
self.conn.execute('''
- INSERT INTO min_sizes (id, min_size)
- SELECT inode, MAX(blockno * ? + size)
- FROM inode_blocks JOIN blocks ON block_id == blocks.id
+ INSERT INTO min_sizes (id, min_size)
+ SELECT inode, MAX(blockno * ? + size)
+ FROM inode_blocks JOIN blocks ON block_id == blocks.id
GROUP BY inode''', (self.max_obj_size,))
self.conn.execute('''
- CREATE TEMPORARY TABLE wrong_sizes AS
+ CREATE TEMPORARY TABLE wrong_sizes AS
SELECT id, size, min_size
FROM inodes JOIN min_sizes USING (id)
WHERE size < min_size''')
@@ -451,10 +452,10 @@ class Fsck(object):
'SELECT inode, COUNT(name_id) FROM contents GROUP BY inode')
self.conn.execute('''
- CREATE TEMPORARY TABLE wrong_refcounts AS
- SELECT id, refcounts.refcount, inodes.refcount
- FROM inodes LEFT JOIN refcounts USING (id)
- WHERE inodes.refcount != refcounts.refcount
+ CREATE TEMPORARY TABLE wrong_refcounts AS
+ SELECT id, refcounts.refcount, inodes.refcount
+ FROM inodes LEFT JOIN refcounts USING (id)
+ WHERE inodes.refcount != refcounts.refcount
OR refcounts.refcount IS NULL''')
for (id_, cnt, cnt_old) in self.conn.query('SELECT * FROM wrong_refcounts'):
@@ -583,17 +584,17 @@ class Fsck(object):
'(id INTEGER PRIMARY KEY, refcount INTEGER NOT NULL)')
try:
self.conn.execute('''
- INSERT INTO refcounts (id, refcount)
- SELECT block_id, COUNT(blockno)
+ INSERT INTO refcounts (id, refcount)
+ SELECT block_id, COUNT(blockno)
FROM inode_blocks
GROUP BY block_id
''')
self.conn.execute('''
- CREATE TEMPORARY TABLE wrong_refcounts AS
- SELECT id, refcounts.refcount, blocks.refcount, obj_id
- FROM blocks LEFT JOIN refcounts USING (id)
- WHERE blocks.refcount != refcounts.refcount
+ CREATE TEMPORARY TABLE wrong_refcounts AS
+ SELECT id, refcounts.refcount, blocks.refcount, obj_id
+ FROM blocks LEFT JOIN refcounts USING (id)
+ WHERE blocks.refcount != refcounts.refcount
OR refcounts.refcount IS NULL''')
for (id_, cnt, cnt_old, obj_id) in self.conn.query('SELECT * FROM wrong_refcounts'):
@@ -660,10 +661,10 @@ class Fsck(object):
' WHERE name_id = refcounts.id)')
self.conn.execute('''
- CREATE TEMPORARY TABLE wrong_refcounts AS
- SELECT id, refcounts.refcount, names.refcount
- FROM names LEFT JOIN refcounts USING (id)
- WHERE names.refcount != refcounts.refcount
+ CREATE TEMPORARY TABLE wrong_refcounts AS
+ SELECT id, refcounts.refcount, names.refcount
+ FROM names LEFT JOIN refcounts USING (id)
+ WHERE names.refcount != refcounts.refcount
OR refcounts.refcount IS NULL''')
for (id_, cnt, cnt_old) in self.conn.query('SELECT * FROM wrong_refcounts'):
@@ -682,7 +683,7 @@ class Fsck(object):
def check_unix(self):
"""Check if file systems for agreement with UNIX conventions
-
+
This means:
- Only directories should have child entries
- Only regular files should have data blocks and a size
@@ -691,7 +692,7 @@ class Fsck(object):
- symlink size is length of target
- names are not longer than 255 bytes
- All directory entries have a valid mode
-
+
Note that none of this is enforced by S3QL. However, as long as S3QL
only communicates with the UNIX FUSE module, none of the above should
happen (and if it does, it would probably confuse the system quite a
@@ -706,7 +707,7 @@ class Fsck(object):
has_children = self.conn.has_val('SELECT 1 FROM contents WHERE parent_inode=? LIMIT 1',
(inode,))
-
+
if stat.S_IFMT(mode) == 0:
if has_children:
mode = mode | stat.S_IFDIR
@@ -717,9 +718,9 @@ class Fsck(object):
self.found_errors = True
self.log_error('Inode %d (%s): directory entry has no type, changed '
- 'to %s.', inode, get_path(inode, self.conn), made_to)
+ 'to %s.', inode, get_path(inode, self.conn), made_to)
self.conn.execute('UPDATE inodes SET mode=? WHERE id=?', (mode, inode))
-
+
if stat.S_ISLNK(mode) and target is None:
self.found_errors = True
self.log_error('Inode %d (%s): symlink does not have target. '
@@ -765,10 +766,10 @@ class Fsck(object):
self.log_error('Inode %d (%s) is not a regular file but has data blocks. '
'This is probably going to confuse your system!',
inode, get_path(inode, self.conn))
-
-
-
+
+
+
for (name, id_p) in self.conn.query('SELECT name, parent_inode FROM contents_v '
'WHERE LENGTH(name) > 255'):
@@ -789,10 +790,10 @@ class Fsck(object):
'SELECT obj_id, COUNT(obj_id) FROM blocks GROUP BY obj_id')
self.conn.execute('''
- CREATE TEMPORARY TABLE wrong_refcounts AS
- SELECT id, refcounts.refcount, objects.refcount
- FROM objects LEFT JOIN refcounts USING (id)
- WHERE objects.refcount != refcounts.refcount
+ CREATE TEMPORARY TABLE wrong_refcounts AS
+ SELECT id, refcounts.refcount, objects.refcount
+ FROM objects LEFT JOIN refcounts USING (id)
+ WHERE objects.refcount != refcounts.refcount
OR refcounts.refcount IS NULL''')
for (id_, cnt, cnt_old) in self.conn.query('SELECT * FROM wrong_refcounts'):
@@ -873,7 +874,7 @@ class Fsck(object):
for (id_,) in self.conn.query('SELECT inode FROM inode_blocks JOIN blocks ON block_id = id '
'WHERE obj_id=? ', (obj_id,)):
- # Same file may lack several blocks, but we want to move it
+ # Same file may lack several blocks, but we want to move it
# only once
if id_ in self.moved_inodes:
continue
@@ -899,10 +900,10 @@ class Fsck(object):
finally:
if sys.stdout.isatty():
sys.stdout.write('\n')
-
+
self.conn.execute('DROP TABLE obj_ids')
self.conn.execute('DROP TABLE IF EXISTS missing')
-
+
def check_objects_size(self):
"""Check objects.size"""
@@ -919,7 +920,7 @@ class Fsck(object):
def resolve_free(self, path, name):
'''Return parent inode and name of an unused directory entry
-
+
The directory entry will be in `path`. If an entry `name` already
exists there, we append a numeric suffix.
'''
@@ -951,7 +952,7 @@ class Fsck(object):
def _add_name(self, name):
'''Get id for *name* and increase refcount
-
+
Name is inserted in table if it does not yet exist.
'''
@@ -1076,16 +1077,16 @@ def main(args=None):
# Check if fs is mounted on this computer
# This is not foolproof but should prevent common mistakes
if is_mounted(options.storage_url):
- raise QuietError('Can not check mounted file system.')
+ raise QuietError('Can not check mounted file system.', exitcode=40)
try:
backend = get_backend(options)
except DanglingStorageURLError as exc:
- raise QuietError(str(exc))
+ raise QuietError(str(exc), exitcode=38)
atexit.register(backend.close)
-
+
log.info('Starting fsck of %s', options.storage_url)
-
+
cachepath = get_backend_cachedir(options.storage_url, options.cachedir)
seq_no = get_seq_no(backend)
db = None
@@ -1105,7 +1106,7 @@ def main(args=None):
if param['seq_no'] > seq_no:
log.warning('File system has not been unmounted cleanly.')
param['needs_fsck'] = True
-
+
elif backend.lookup('s3ql_metadata')['seq_no'] != param['seq_no']:
log.warning('Remote metadata is outdated.')
param['needs_fsck'] = True
@@ -1118,10 +1119,11 @@ def main(args=None):
# Check revision
if param['revision'] < CURRENT_FS_REV:
- raise QuietError('File system revision too old, please run `s3qladm upgrade` first.')
+ raise QuietError('File system revision too old, please run `s3qladm upgrade` first.',
+ exitcode=32)
elif param['revision'] > CURRENT_FS_REV:
raise QuietError('File system revision too new, please update your '
- 'S3QL installation.')
+ 'S3QL installation.', exitcode=33)
if param['seq_no'] < seq_no:
print(textwrap.fill(textwrap.dedent('''\
@@ -1129,15 +1131,15 @@ def main(args=None):
has not been unmounted cleanly or the data has not yet propagated through the backend.
In the later case, waiting for a while should fix the problem, in the former case you
should try to run fsck on the computer where the file system has been mounted most
- recently.
+ recently.
''')))
print('Enter "continue" to use the outdated data anyway:',
'> ', sep='\n', end='')
if options.batch:
- raise QuietError('(in batch mode, exiting)')
+ raise QuietError('(in batch mode, exiting)', exitcode=41)
if sys.stdin.readline().strip() != 'continue':
- raise QuietError()
+ raise QuietError(exitcode=42)
param['seq_no'] = seq_no
param['needs_fsck'] = True
@@ -1165,7 +1167,7 @@ def main(args=None):
raise QuietError('Local metadata is corrupted. Remove or repair the following '
'files manually and re-run fsck:\n'
+ cachepath + '.db (corrupted)\n'
- + cachepath + '.param (intact)')
+ + cachepath + '.param (intact)', exitcode=43)
else:
with tempfile.TemporaryFile() as tmpfh:
def do_read(fh):
@@ -1175,12 +1177,12 @@ def main(args=None):
log.info('Downloading and decompressing metadata...')
backend.perform_read(do_read, "s3ql_metadata")
-
+
log.info("Reading metadata...")
tmpfh.seek(0)
db = restore_metadata(tmpfh, cachepath + '.db')
- # Increase metadata sequence no
+ # Increase metadata sequence no
param['seq_no'] += 1
param['needs_fsck'] = True
backend['s3ql_seq_no_%d' % param['seq_no']] = b'Empty'
@@ -1192,7 +1194,7 @@ def main(args=None):
param['max_inode'] = db.get_val('SELECT MAX(id) FROM inodes')
if fsck.uncorrectable_errors:
- raise QuietError("Uncorrectable errors found, aborting.")
+ raise QuietError("Uncorrectable errors found, aborting.", exitcode=44+128)
if os.path.exists(cachepath + '-cache'):
os.rmdir(cachepath + '-cache')
@@ -1217,7 +1219,7 @@ def main(args=None):
fh.seek(0)
stream_write_bz2(fh, obj_fh)
return obj_fh
-
+
log.info("Compressing and uploading metadata...")
obj_fh = backend.perform_write(do_write, "s3ql_metadata_new", metadata=param,
is_compressed=True)
@@ -1233,7 +1235,12 @@ def main(args=None):
db.close()
log.info('Completed fsck of %s', options.storage_url)
-
+
+ if fsck.found_errors:
+ sys.exit(128)
+ else:
+ sys.exit(0)
+
def renumber_inodes(db):
'''Renumber inodes'''
@@ -1292,7 +1299,7 @@ def renumber_inodes(db):
def escape(path):
'''Escape slashes in path so that is usable as a file name'''
-
+
return path[1:].replace(b'_', b'__').replace(b'/', b'_')
if __name__ == '__main__':
diff --git a/src/s3ql/inherit_docstrings.py b/src/s3ql/inherit_docstrings.py
index 426b4d0..b084198 100644
--- a/src/s3ql/inherit_docstrings.py
+++ b/src/s3ql/inherit_docstrings.py
@@ -31,7 +31,7 @@ def copy_ancestor_docstring(fn):
def _copy_ancestor_docstring(mro, fn):
'''Decorator to set docstring for *fn* from *mro*'''
-
+
if fn.__doc__ is not None:
raise RuntimeError('Function already has docstring')
@@ -84,7 +84,7 @@ DECORATORS = (('copy_ancestor_docstring', _copy_ancestor_docstring),
('prepend_ancestor_docstring', _prepend_ancestor_docstring))
class InheritableDocstrings(type):
-
+
@classmethod
def __prepare__(cls, name, bases, **kwds):
classdict = super().__prepare__(name, bases, *kwds)
@@ -93,7 +93,7 @@ class InheritableDocstrings(type):
# Inject decorators into class namespace
for (name, fn) in DECORATORS:
classdict[name] = partial(fn, mro)
-
+
return classdict
def __new__(cls, name, bases, classdict):
@@ -103,19 +103,18 @@ class InheritableDocstrings(type):
# (Pythonbug? reported as http://bugs.python.org/issue18334)
if dec_name not in classdict:
continue
-
+
# Make sure that class definition hasn't messed with decorator
if getattr(classdict[dec_name], 'func', None) is not fn:
raise RuntimeError('No %s attribute may be created in classes using '
'the InheritableDocstrings metaclass' % name)
-
+
# Delete decorator from class namespace
del classdict[dec_name]
-
+
return super().__new__(cls, name, bases, classdict)
# Derive new metaclass to add docstring inheritance
class ABCDocstMeta(ABCMeta, InheritableDocstrings):
pass
-
diff --git a/src/s3ql/inode_cache.py b/src/s3ql/inode_cache.py
index 12e6b09..0b1793a 100644
--- a/src/s3ql/inode_cache.py
+++ b/src/s3ql/inode_cache.py
@@ -64,7 +64,7 @@ class _Inode(object):
def __hash__(self):
return self.id
-
+
def copy(self):
copy = _Inode(self.generation)
@@ -82,32 +82,32 @@ class _Inode(object):
class InodeCache(object):
'''
This class maps the `inode` SQL table to a dict, caching the rows.
-
+
If the cache is full and a row is not in the cache, the least-recently
retrieved row is deleted from the cache. This means that accessing
- cached rows will *not* change the order of their expiration.
-
- Attributes:
+ cached rows will *not* change the order of their expiration.
+
+ Attributes:
-----------
:attrs: inode indexed dict holding the attributes
:cached_rows: list of the inodes that are in cache
- :pos: position of the most recently retrieved inode in
+ :pos: position of the most recently retrieved inode in
'cached_rows'.
-
+
Notes
-----
-
+
Callers should keep in mind that the changes of the returned inode
object will only be written to the database if the inode is still
- in the cache when its attributes are updated: it is possible for
+ in the cache when its attributes are updated: it is possible for
the caller to keep a reference to an inode when that
inode has already been expired from the InodeCache. Modifications
to this inode object will be lost(!).
-
+
Callers should therefore use the returned inode objects only
as long as they can guarantee that no other calls to InodeCache
- are made that may result in expiration of inodes from the cache.
-
+ are made that may result in expiration of inodes from the cache.
+
Moreover, the caller must make sure that he does not call
InodeCache methods while a database transaction is active that
may be rolled back. This would rollback database updates
@@ -123,7 +123,7 @@ class InodeCache(object):
self.generation = inode_gen
# Fill the cache with dummy data, so that we don't have to
- # check if the cache is full or not (it will always be full)
+ # check if the cache is full or not (it will always be full)
for _ in range(CACHE_SIZE):
self.cached_rows.append(None)
diff --git a/src/s3ql/lock.py b/src/s3ql/lock.py
index 726ebef..2dcc126 100644
--- a/src/s3ql/lock.py
+++ b/src/s3ql/lock.py
@@ -24,7 +24,7 @@ def parse_args(args):
description=textwrap.dedent('''\
Makes the given directory tree(s) immutable. No changes of any sort can
be performed on the tree after that. Immutable entries can only be
- deleted with s3qlrm.
+ deleted with s3qlrm.
'''))
parser.add_debug()
diff --git a/src/s3ql/logging.py b/src/s3ql/logging.py
index 2d2de95..41d76e4 100644
--- a/src/s3ql/logging.py
+++ b/src/s3ql/logging.py
@@ -43,17 +43,20 @@ class QuietError(Exception):
string containing sufficient information about the problem.
'''
- def __init__(self, msg=''):
+ def __init__(self, msg='', exitcode=1):
super().__init__()
self.msg = msg
+ #: Exit code to use when terminating process
+ self.exitcode = exitcode
+
def __str__(self):
return self.msg
def create_handler(target):
'''Create logging handler for given target'''
-
+
if target.lower() == 'syslog':
handler = logging.handlers.SysLogHandler('/dev/log')
formatter = logging.Formatter(os.path.basename(sys.argv[0])
@@ -67,13 +70,15 @@ def create_handler(target):
try:
os.makedirs(dirname)
except PermissionError:
- raise QuietError('No permission to create log file %s' % fullpath)
+ raise QuietError('No permission to create log file %s' % fullpath,
+ exitcode=10)
try:
handler = logging.handlers.RotatingFileHandler(fullpath,
maxBytes=1024 ** 2, backupCount=5)
except PermissionError:
- raise QuietError('No permission to write log file %s' % fullpath)
+ raise QuietError('No permission to write log file %s' % fullpath,
+ exitcode=10)
formatter = logging.Formatter('%(asctime)s.%(msecs)03d [pid=%(process)r, '
'thread=%(threadName)r, module=%(name)r, '
@@ -82,7 +87,7 @@ def create_handler(target):
handler.setFormatter(formatter)
return handler
-
+
def setup_logging(options):
root_logger = logging.getLogger()
if root_logger.handlers:
@@ -132,8 +137,8 @@ def setup_logging(options):
else:
logging.captureWarnings(capture=True)
-
-
+
+
return stdout_handler
def setup_excepthook():
@@ -149,12 +154,14 @@ def setup_excepthook():
# force_log attribute ensures that logging handler will
# not raise exception (if EXCEPTION_SEVERITY is set)
root_logger.error(val.msg, extra={ 'force_log': True })
+ sys.exit(val.exitcode)
else:
# force_log attribute ensures that logging handler will
# not raise exception (if EXCEPTION_SEVERITY is set)
root_logger.error('Uncaught top-level exception:',
exc_info=(type_, val, tb),
extra={ 'force_log': True})
+ sys.exit(1)
sys.excepthook = excepthook
diff --git a/src/s3ql/metadata.py b/src/s3ql/metadata.py
index 4cb7bfd..91eaad6 100644
--- a/src/s3ql/metadata.py
+++ b/src/s3ql/metadata.py
@@ -64,17 +64,17 @@ DUMP_SPEC = [
def restore_metadata(fh, dbfile):
'''Read metadata from *fh* and write into *dbfile*
-
+
Return database connection to *dbfile*.
-
+
*fh* must be able to return an actual file descriptor from
its `fileno` method.
-
+
*dbfile* will be created with 0600 permissions. Data is
first written into a temporary file *dbfile* + '.tmp', and
the file is renamed once all data has been loaded.
-
-
+
+
'''
tmpfile = dbfile + '.tmp'
@@ -82,26 +82,26 @@ def restore_metadata(fh, dbfile):
stat.S_IRUSR | stat.S_IWUSR)
try:
os.close(fd)
-
+
db = Connection(tmpfile)
db.execute('PRAGMA locking_mode = NORMAL')
db.execute('PRAGMA synchronous = OFF')
db.execute('PRAGMA journal_mode = OFF')
create_tables(db)
-
+
for (table, _, columns) in DUMP_SPEC:
log.info('..%s..', table)
load_table(table, columns, db=db, fh=fh)
db.execute('ANALYZE')
-
+
# We must close the database to rename it
db.close()
except:
os.unlink(tmpfile)
raise
-
+
os.rename(tmpfile, dbfile)
-
+
return Connection(dbfile)
def cycle_metadata(backend):
@@ -120,7 +120,7 @@ def cycle_metadata(backend):
def dump_metadata(db, fh):
'''Dump metadata into fh
-
+
*fh* must be able to return an actual file descriptor from
its `fileno` method.
'''
@@ -131,22 +131,22 @@ def dump_metadata(db, fh):
# (need to access DB to actually release locks)
db.execute('PRAGMA locking_mode = NORMAL')
db.has_val('SELECT rowid FROM %s LIMIT 1' % DUMP_SPEC[0][0])
-
+
for (table, order, columns) in DUMP_SPEC:
log.info('..%s..', table)
dump_table(table, order, columns, db=db, fh=fh)
-
+
finally:
db.execute('PRAGMA locking_mode = %s' % locking_mode)
-
-
+
+
def create_tables(conn):
# Table of storage objects
# Refcount is included for performance reasons
conn.execute("""
CREATE TABLE objects (
id INTEGER PRIMARY KEY AUTOINCREMENT,
- refcount INT NOT NULL,
+ refcount INT NOT NULL,
size INT NOT NULL
)""")
@@ -157,7 +157,7 @@ def create_tables(conn):
id INTEGER PRIMARY KEY,
hash BLOB(16) UNIQUE,
refcount INT,
- size INT NOT NULL,
+ size INT NOT NULL,
obj_id INTEGER NOT NULL REFERENCES objects(id)
)""")
@@ -216,7 +216,7 @@ def create_tables(conn):
name_id INT NOT NULL REFERENCES names(id),
inode INT NOT NULL REFERENCES inodes(id),
parent_inode INT NOT NULL REFERENCES inodes(id),
-
+
UNIQUE (parent_inode, name_id)
)""")
@@ -226,14 +226,14 @@ def create_tables(conn):
inode INTEGER NOT NULL REFERENCES inodes(id),
name_id INTEGER NOT NULL REFERENCES names(id),
value BLOB NOT NULL,
-
- PRIMARY KEY (inode, name_id)
+
+ PRIMARY KEY (inode, name_id)
)""")
# Shortcuts
conn.execute("""
CREATE VIEW contents_v AS
- SELECT * FROM contents JOIN names ON names.id = name_id
+ SELECT * FROM contents JOIN names ON names.id = name_id
""")
conn.execute("""
CREATE VIEW ext_attributes_v AS
diff --git a/src/s3ql/mkfs.py b/src/s3ql/mkfs.py
index 8144820..1597b4e 100644
--- a/src/s3ql/mkfs.py
+++ b/src/s3ql/mkfs.py
@@ -8,8 +8,8 @@ This program can be distributed under the terms of the GNU GPLv3.
from .logging import logging, setup_logging, QuietError
from . import CURRENT_FS_REV
-from .backends.common import get_backend, BetterBackend, DanglingStorageURLError
-from .backends import s3
+from .backends.common import BetterBackend, DanglingStorageURLError
+from .backends import s3, get_backend
from .common import get_backend_cachedir, CTRL_INODE, stream_write_bz2, PICKLE_PROTOCOL
from .database import Connection
from .metadata import dump_metadata, create_tables
@@ -65,7 +65,7 @@ def init_tables(conn):
| stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH,
os.getuid(), os.getgid(), timestamp, timestamp, timestamp, 1))
- # Insert control inode, the actual values don't matter that much
+ # Insert control inode, the actual values don't matter that much
conn.execute("INSERT INTO inodes (id,mode,uid,gid,mtime,atime,ctime,refcount) "
"VALUES (?,?,?,?,?,?,?,?)",
(CTRL_INODE, stat.S_IFREG | stat.S_IRUSR | stat.S_IWUSR,
@@ -108,7 +108,7 @@ def main(args=None):
'accessed using SSL!')
log.warning('(cf. https://forums.aws.amazon.com/thread.jspa?threadID=130560)')
-
+
if 's3ql_metadata' in plain_backend:
if not options.force:
raise QuietError("Found existing file system! Use --force to overwrite")
@@ -144,7 +144,7 @@ def main(args=None):
backend = BetterBackend(data_pw, ('lzma', 2), plain_backend)
atexit.unregister(plain_backend.close)
atexit.register(backend.close)
-
+
# Setup database
cachepath = get_backend_cachedir(options.storage_url, options.cachedir)
@@ -189,7 +189,7 @@ def main(args=None):
obj_fh = backend.perform_write(do_write, "s3ql_metadata", metadata=param,
is_compressed=True)
backend.store('s3ql_seq_no_%d' % param['seq_no'], b'Empty')
-
+
log.info('Wrote %.2f MiB of compressed metadata.', obj_fh.get_obj_size() / 1024 ** 2)
with open(cachepath + '.params', 'wb') as fh:
pickle.dump(param, fh, PICKLE_PROTOCOL)
diff --git a/src/s3ql/mount.py b/src/s3ql/mount.py
index 36ab568..2b7a217 100644
--- a/src/s3ql/mount.py
+++ b/src/s3ql/mount.py
@@ -8,7 +8,8 @@ This program can be distributed under the terms of the GNU GPLv3.
from .logging import logging, setup_logging, QuietError
from . import fs, CURRENT_FS_REV
-from .backends.common import get_backend_factory, BackendPool, DanglingStorageURLError
+from .backends.common import BackendPool, DanglingStorageURLError
+from .backends import get_backend_factory
from .block_cache import BlockCache
from .common import (get_backend_cachedir, get_seq_no, stream_write_bz2, stream_read_bz2,
PICKLE_PROTOCOL)
@@ -41,7 +42,7 @@ log = logging.getLogger(__name__)
def install_thread_excepthook():
"""work around sys.excepthook thread bug
-
+
See http://bugs.python.org/issue1230540.
Call once from __main__ before creating any threads. If using
@@ -72,13 +73,13 @@ def main(args=None):
args = sys.argv[1:]
options = parse_args(args)
-
+
# Save handler so that we can remove it when daemonizing
stdout_log_handler = setup_logging(options)
if not os.path.exists(options.mountpoint):
- raise QuietError('Mountpoint does not exist.')
-
+ raise QuietError('Mountpoint does not exist.', exitcode=36)
+
if options.threads is None:
options.threads = determine_threads(options)
@@ -91,10 +92,11 @@ def main(args=None):
# each upload thread (because each thread is using at least one socket and
# at least one temporary file)
avail_fd -= 32 + 3 * options.threads
-
+
if options.max_cache_entries is None:
if avail_fd <= 64:
- raise QuietError("Not enough available file descriptors.")
+ raise QuietError("Not enough available file descriptors.",
+ exitcode=37)
log.info('Autodetected %d file descriptors available for cache entries',
avail_fd)
options.max_cache_entries = avail_fd
@@ -112,7 +114,7 @@ def main(args=None):
backend_factory = get_backend_factory(options)
backend_pool = BackendPool(backend_factory)
atexit.register(backend_pool.flush)
-
+
# Get paths
cachepath = get_backend_cachedir(options.storage_url, options.cachedir)
@@ -121,10 +123,11 @@ def main(args=None):
with backend_pool() as backend:
(param, db) = get_metadata(backend, cachepath)
except DanglingStorageURLError as exc:
- raise QuietError(str(exc))
+ raise QuietError(str(exc), exitcode=38)
if param['max_obj_size'] < options.min_obj_size:
- raise QuietError('Maximum object size must be bigger than minimum object size.')
+ raise QuietError('Maximum object size must be bigger than minimum object size.',
+ exitcode=2)
# Handle --cachesize
rec_cachesize = options.max_cache_entries * param['max_obj_size'] / 2
@@ -135,7 +138,7 @@ def main(args=None):
elif options.cachesize > avail_cache:
log.warning('Warning! Requested cache size %d MB, but only %d MB available',
options.cachesize / 1024, avail_cache / 1024)
-
+
if options.nfs:
# NFS may try to look up '..', so we have to speed up this kind of query
log.info('Creating NFS indices...')
@@ -158,8 +161,8 @@ def main(args=None):
try:
llfuse.init(operations, options.mountpoint, get_fuse_opts(options))
except RuntimeError as exc:
- raise QuietError(str(exc))
-
+ raise QuietError(str(exc), exitcode=39)
+
unmount_clean = False
def unmount():
log.info("Unmounting file system...")
@@ -168,7 +171,7 @@ def main(args=None):
with llfuse.lock:
llfuse.close(unmount=unmount_clean)
cm.callback(unmount)
-
+
if options.fg:
faulthandler.enable()
faulthandler.register(signal.SIGUSR1)
@@ -180,12 +183,12 @@ def main(args=None):
faulthandler.enable(crit_log_fh)
faulthandler.register(signal.SIGUSR1, file=crit_log_fh)
daemonize(options.cachedir)
-
+
mark_metadata_dirty(backend, cachepath, param)
-
+
block_cache.init(options.threads)
cm.callback(block_cache.destroy)
-
+
metadata_upload_thread.start()
cm.callback(metadata_upload_thread.join)
cm.callback(metadata_upload_thread.stop)
@@ -193,7 +196,7 @@ def main(args=None):
commit_thread.start()
cm.callback(commit_thread.join)
cm.callback(commit_thread.stop)
-
+
if options.upstart:
os.kill(os.getpid(), signal.SIGSTOP)
@@ -289,7 +292,7 @@ def get_system_memory():
If amount cannot be determined, emits warning and
returns -1.
'''
-
+
# MacOS X doesn't support sysconf('SC_PHYS_PAGES')
if platform.system() == 'Darwin':
try:
@@ -305,9 +308,9 @@ def get_system_memory():
if not hit:
log.warning('Cannot determine system memory, unable to parse sysctl output.')
return -1
-
+
return int(hit.group(1))
-
+
else:
try:
return os.sysconf('SC_PHYS_PAGES') * os.sysconf('SC_PAGESIZE')
@@ -315,7 +318,7 @@ def get_system_memory():
log.warning('Unable to determine number of CPU cores (sysconf failed).')
return -1
-
+
# Memory required for LZMA compression in MB (from xz(1))
LZMA_MEMORY = { 0: 3, 1: 9, 2: 17, 3: 32, 4: 48,
5: 94, 6: 94, 7: 186, 8: 370, 9: 674 }
@@ -373,7 +376,8 @@ def get_metadata(backend, cachepath):
log.info('Ignoring locally cached metadata (outdated).')
param = backend.lookup('s3ql_metadata')
elif param['seq_no'] > seq_no:
- raise QuietError("File system not unmounted cleanly, run fsck!")
+ raise QuietError("File system not unmounted cleanly, run fsck!",
+ exitcode=30)
else:
log.info('Using cached metadata.')
db = Connection(cachepath + '.db')
@@ -382,24 +386,28 @@ def get_metadata(backend, cachepath):
# Check for unclean shutdown
if param['seq_no'] < seq_no:
- raise QuietError('Backend reports that fs is still mounted elsewhere, aborting.')
+ raise QuietError('Backend reports that fs is still mounted elsewhere, aborting.',
+ exitcode=31)
# Check revision
if param['revision'] < CURRENT_FS_REV:
- raise QuietError('File system revision too old, please run `s3qladm upgrade` first.')
+ raise QuietError('File system revision too old, please run `s3qladm upgrade` first.',
+ exitcode=32)
elif param['revision'] > CURRENT_FS_REV:
raise QuietError('File system revision too new, please update your '
- 'S3QL installation.')
+ 'S3QL installation.', exitcode=33)
# Check that the fs itself is clean
if param['needs_fsck']:
- raise QuietError("File system damaged or not unmounted cleanly, run fsck!")
+ raise QuietError("File system damaged or not unmounted cleanly, run fsck!",
+ exitcode=30)
if time.time() - param['last_fsck'] > 60 * 60 * 24 * 31:
log.warning('Last file system check was more than 1 month ago, '
'running fsck.s3ql is recommended.')
if param['max_inode'] > 2 ** 32 - 50000:
- raise QuietError('Insufficient free inodes, fsck run required.')
+ raise QuietError('Insufficient free inodes, fsck run required.',
+ exitcode=34)
elif param['max_inode'] > 2 ** 31:
log.warning('Few free inodes remaining, running fsck is recommended')
@@ -413,33 +421,38 @@ def get_metadata(backend, cachepath):
log.info('Downloading and decompressing metadata...')
backend.perform_read(do_read, "s3ql_metadata")
-
+
log.info("Reading metadata...")
tmpfh.seek(0)
db = restore_metadata(tmpfh, cachepath + '.db')
with open(cachepath + '.params', 'wb') as fh:
pickle.dump(param, fh, PICKLE_PROTOCOL)
-
+
return (param, db)
def mark_metadata_dirty(backend, cachepath, param):
'''Mark metadata as dirty and increase sequence number'''
-
+
param['seq_no'] += 1
param['needs_fsck'] = True
- backend['s3ql_seq_no_%d' % param['seq_no']] = b'Empty'
with open(cachepath + '.params', 'wb') as fh:
pickle.dump(param, fh, PICKLE_PROTOCOL)
- param['needs_fsck'] = False
+ # Fsync to make sure that the updated sequence number is committed to
+ # disk. Otherwise, a crash immediately after mount could result in both
+ # the local and remote metadata appearing to be out of date.
+ fh.flush()
+ os.fsync(fh.fileno())
+ backend['s3ql_seq_no_%d' % param['seq_no']] = b'Empty'
+ param['needs_fsck'] = False
def get_fuse_opts(options):
'''Return fuse options for given command line options'''
fuse_opts = [ "nonempty", 'fsname=%s' % options.storage_url,
'subtype=s3ql' ]
-
+
if platform.system() == 'Darwin':
# FUSE4X and OSXFUSE claim to support nonempty, but
# neither of them actually do.
@@ -480,7 +493,8 @@ def parse_args(args):
'owner', 'users', 'nobootwait'):
continue
elif opt == 'ro':
- raise QuietError('Read-only mounting not supported.')
+ raise QuietError('Read-only mounting not supported.',
+ exitcode=35)
args.insert(pos, '--' + opt)
def compression_type(s):
@@ -498,7 +512,7 @@ def parse_args(args):
if alg == 'none':
alg = None
return (alg, lvl)
-
+
parser = ArgumentParser(
description="Mount an S3QL file system.")
@@ -588,9 +602,9 @@ class MetadataUploadThread(Thread):
Periodically upload metadata. Upload is done every `interval`
seconds, and whenever `event` is set. To terminate thread,
set `quit` attribute as well as `event` event.
-
+
This class uses the llfuse global lock. When calling objects
- passed in the constructor, the global lock is acquired first.
+ passed in the constructor, the global lock is acquired first.
'''
def __init__(self, backend_pool, param, db, interval):
@@ -668,7 +682,7 @@ class MetadataUploadThread(Thread):
def setup_exchook():
'''Send SIGTERM if any other thread terminates with an exception
-
+
The exc_info will be saved in the list object returned
by this function.
'''
@@ -705,7 +719,7 @@ def setup_exchook():
class CommitThread(Thread):
'''
Periodically upload dirty blocks.
-
+
This class uses the llfuse global lock. When calling objects
passed in the constructor, the global lock is acquired first.
'''
@@ -722,7 +736,7 @@ class CommitThread(Thread):
while not self.stop_event.is_set():
did_sth = False
-
+
with llfuse.lock:
stamp = time.time()
# Need to make copy, since we aren't allowed to change
diff --git a/src/s3ql/multi_lock.py b/src/s3ql/multi_lock.py
index c0da049..90f7edd 100644
--- a/src/s3ql/multi_lock.py
+++ b/src/s3ql/multi_lock.py
@@ -16,14 +16,14 @@ log = logging.getLogger(__name__)
class MultiLock:
"""Provides locking for multiple objects.
-
+
This class provides locking for a dynamically changing set of objects: The
`acquire` and `release` methods have an additional argument, the locking
key. Only locks with the same key can actually see each other, so that
several threads can hold locks with different locking keys at the same time.
-
+
MultiLock instances can be used as context managers.
-
+
Note that it is actually possible for one thread to release a lock that has
been obtained by a different thread. This is not a bug but a feature.
"""
@@ -49,7 +49,7 @@ class MultiLock:
with self.cond:
if not self.cond.wait_for(lambda: key not in self.locked_keys, timeout):
return False
-
+
self.locked_keys.add(key)
def release(self, *key, noerror=False):
diff --git a/src/s3ql/oauth_client.py b/src/s3ql/oauth_client.py
new file mode 100644
index 0000000..9b70117
--- /dev/null
+++ b/src/s3ql/oauth_client.py
@@ -0,0 +1,104 @@
+'''
+oauth_client.py - this file is part of S3QL (http://s3ql.googlecode.com)
+
+Copyright (C) Nikolaus Rath <Nikolaus@rath.org>
+
+This program can be distributed under the terms of the GNU GPLv3.
+'''
+
+from .logging import logging, setup_logging, QuietError
+from .parse_args import ArgumentParser
+import sys
+import textwrap
+import requests
+import time
+
+log = logging.getLogger(__name__)
+
+# S3QL client id and client secret for Google APIs.
+# Don't get your hopes up, this isn't truly secret.
+CLIENT_ID = '381875429714-6pch5vnnmqab454c68pkt8ugm86ef95v.apps.googleusercontent.com'
+CLIENT_SECRET = 'HGl8fJeVML-gZ-1HSZRNZPz_'
+
+def parse_args(args):
+ '''Parse command line'''
+
+ parser = ArgumentParser(
+ description=textwrap.dedent('''\
+ Obtain OAuth2 refresh token for Google Storage
+ '''))
+
+ parser.add_debug_modules()
+ parser.add_quiet()
+ parser.add_version()
+
+ return parser.parse_args(args)
+
+def _log_response(r):
+ '''Log server response'''
+
+ if not log.isEnabledFor(logging.DEBUG):
+ return
+
+ s = [ 'Server response:',
+ '%03d %s' % (r.status_code, r.reason) ]
+ for tup in r.headers.items():
+ s.append('%s: %s' % tup)
+
+ s.append('')
+ s.append(r.text)
+
+ log.debug('\n'.join(s))
+
+def _parse_response(r):
+
+ _log_response(r)
+ if r.status_code != requests.codes.ok:
+ raise QuietError('Connection failed with: %d %s'
+ % (r.status_code, r.reason))
+
+ return r.json()
+
+def main(args=None):
+
+ if args is None:
+ args = sys.argv[1:]
+
+ options = parse_args(args)
+ setup_logging(options)
+
+ cli = requests.Session()
+
+ r = cli.post('https://accounts.google.com/o/oauth2/device/code',
+ data={ 'client_id': CLIENT_ID,
+ 'scope': 'https://www.googleapis.com/auth/devstorage.read_write' },
+ verify=True, allow_redirects=False, timeout=20)
+ req_json = _parse_response(r)
+
+ print(textwrap.fill('Please open %s in your browser and enter the following '
+ 'user code: %s' % (req_json['verification_url'],
+ req_json['user_code'])))
+
+ while True:
+ log.debug('polling..')
+ time.sleep(req_json['interval'])
+
+ r = cli.post('https://accounts.google.com/o/oauth2/token',
+ data={ 'client_id': CLIENT_ID,
+ 'client_secret': CLIENT_SECRET,
+ 'code': req_json['device_code'],
+ 'grant_type': 'http://oauth.net/grant_type/device/1.0' },
+ verify=True, allow_redirects=False, timeout=20)
+ resp_json = _parse_response(r)
+ r.close()
+
+ if 'error' in resp_json:
+ if resp_json['error'] == 'authorization_pending':
+ continue
+ else:
+ raise QuietError('Authentication failed: ' + resp_json['error'])
+ else:
+ break
+
+ print('Success. Your refresh token is:\n',
+ resp_json['refresh_token'])
diff --git a/src/s3ql/parse_args.py b/src/s3ql/parse_args.py
index 579c57f..adba8a9 100644
--- a/src/s3ql/parse_args.py
+++ b/src/s3ql/parse_args.py
@@ -9,25 +9,25 @@ This module provides a customized ArgumentParser class. Differences
are:
* a --version argument is added by default
-
- * convenience functions are available for adding --quiet,
+
+ * convenience functions are available for adding --quiet,
--debug, --cachedir, --log and --authfile options.
-
+
* instead of the usage string one can pass a usage list. The first
element will be prefixed with ``usage: `` as usual. Additional
elements will be printed on separate lines and prefixed with
`` or: ``.
-
+
* When element of an usage list, the ``DEFAULT_USAGE`` object
will be replaced by the automatically generated usage message,
excluding any --help arguments.
-
+
* When specified on its own, the replacement will be done including
any --help arguments.
-
+
* The ``usage`` and ``add_help`` settings are inherited from the
- parent parser to the subparsers.
-
+ parent parser to the subparsers.
+
'''
# Pylint really gets confused by this module
@@ -48,7 +48,7 @@ class HelpFormatter(argparse.HelpFormatter):
def _format_usage(self, usage, actions, groups, prefix):
'''Special handling for usage lists
-
+
If usage is a list object, its elements will be printed on
separate lines. DEFAULT_USAGE will be replaced by the
default usage string of the parser (but, if `usage`` is a list,
@@ -143,12 +143,12 @@ class ArgumentParser(argparse.ArgumentParser):
self.add_argument("--no-ssl", action="store_true", default=False,
help="Do not use secure (ssl) connections when connecting "
"to remote servers.")
-
+
self.add_argument("--ssl-ca-path", metavar='path', default=None, type=str,
help="File or directory or containing the trusted CA certificates. "
"If not specified, the defaults compiled into the system's "
"OpenSSL library are used.")
-
+
def add_debug_modules(self):
self.add_argument("--debug", action="append", metavar='<module>',
help="activate debugging output from <module>. Use `all` "
@@ -179,7 +179,7 @@ class ArgumentParser(argparse.ArgumentParser):
def add_fatal_warnings(self):
# Make all log messages of severity warning or higher raise
# exceptions. This option is not listed in the --help output and used by
- # the unit tests.
+ # the unit tests.
self.add_argument("--fatal-warnings", action='store_true', default=False,
help=argparse.SUPPRESS)
@@ -206,7 +206,7 @@ class ArgumentParser(argparse.ArgumentParser):
return super().add_subparsers(**kw)
def parse_args(self, *args, **kwargs):
-
+
try:
return super().parse_args(*args, **kwargs)
except ArgumentError as exc:
@@ -214,7 +214,7 @@ class ArgumentParser(argparse.ArgumentParser):
def storage_url_type(s):
'''Validate and canonicalize storage url'''
-
+
if not re.match(r'^([a-zA-Z0-9]+)://(.+)$', s):
raise ArgumentTypeError('%s is not a valid storage url.' % s)
diff --git a/src/s3ql/remove.py b/src/s3ql/remove.py
index f7fe218..88e83f8 100644
--- a/src/s3ql/remove.py
+++ b/src/s3ql/remove.py
@@ -23,7 +23,7 @@ def parse_args(args):
parser = ArgumentParser(
description=textwrap.dedent('''\
Recursively delete files and directories in an S3QL file system,
- including immutable entries.
+ including immutable entries.
'''))
parser.add_debug()
diff --git a/src/s3ql/umount.py b/src/s3ql/umount.py
index 717ff43..289ea6f 100644
--- a/src/s3ql/umount.py
+++ b/src/s3ql/umount.py
@@ -22,13 +22,13 @@ log = logging.getLogger(__name__)
def parse_args(args):
'''Parse command line
-
- This function writes to stdout/stderr and may call `system.exit()` instead
+
+ This function writes to stdout/stderr and may call `system.exit()` instead
of throwing an exception if it encounters errors.
'''
parser = ArgumentParser(
- description=textwrap.dedent('''\
+ description=textwrap.dedent('''\
Unmounts an S3QL file system. The command returns only after all data
has been uploaded to the backend.'''))
@@ -55,18 +55,18 @@ class UmountError(Exception):
message = 'internal error'
exitcode = 3
-
+
def __init__(self, mountpoint):
super().__init__()
self.mountpoint = mountpoint
-
+
def __str__(self):
return self.message
class UmountSubError(UmountError):
message = 'Unmount subprocess failed.'
exitcode = 2
-
+
class MountInUseError(UmountError):
message = 'In use.'
exitcode = 1
@@ -103,12 +103,12 @@ def get_cmdline(pid):
return output
else:
return None
-
+
def blocking_umount(mountpoint):
'''Invoke fusermount and wait for daemon to terminate.'''
with open('/dev/null', 'wb') as devnull:
- if subprocess.call(['fuser', '-m', mountpoint], stdout=devnull,
+ if subprocess.call(['fuser', '-m', mountpoint], stdout=devnull,
stderr=devnull) == 0:
raise MountInUseError(mountpoint)
@@ -175,7 +175,7 @@ def main(args=None):
setup_logging(options)
assert_s3ql_mountpoint(options.mountpoint)
-
+
try:
if options.lazy:
lazy_umount(options.mountpoint)
@@ -192,7 +192,7 @@ def main(args=None):
except UmountError as err:
print('%s: %s' % (options.mountpoint, err), file=sys.stderr)
sys.exit(err.exitcode)
-
+
sys.exit(0)
if __name__ == '__main__':
diff --git a/tests/common.py b/tests/common.py
index e4ea947..e677dff 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -38,14 +38,14 @@ def catch_logmsg(pattern, level=logging.WARNING, count=None):
logger_class = logging.getLoggerClass()
handle_orig = logger_class.handle
caught = [0]
-
+
@wraps(handle_orig)
def handle_new(self, record):
if (record.levelno != level
or not re.search(pattern, record.msg)):
return handle_orig(self, record)
caught[0] += 1
-
+
logger_class.handle = handle_new
try:
yield
@@ -122,7 +122,7 @@ class AsyncFn(ExceptionStoringThread):
def retry(timeout, fn, *a, **kw):
"""Wait for fn(*a, **kw) to return True.
-
+
If the return value of fn() returns something True, this value
is returned. Otherwise, the function is called repeatedly for
`timeout` seconds. If the timeout is reached, `RetryTimeoutError` is
@@ -153,7 +153,7 @@ def skip_if_no_fusermount():
with subprocess.Popen(['which', 'fusermount'], stdout=subprocess.PIPE,
universal_newlines=True) as which:
fusermount_path = which.communicate()[0].strip()
-
+
if not fusermount_path or which.returncode != 0:
raise unittest.SkipTest("Can't find fusermount executable")
@@ -175,7 +175,7 @@ def skip_if_no_fusermount():
def skip_without_rsync():
try:
- with open('/dev/null', 'wb') as null:
+ with open('/dev/null', 'wb') as null:
subprocess.call(['rsync', '--version'], stdout=null,
stderr=subprocess.STDOUT,)
except FileNotFoundError:
@@ -184,12 +184,12 @@ def skip_without_rsync():
def populate_dir(path, entries=1000, size=20*1024*1024,
pooldir='/usr/bin', seed=None):
'''Populate directory with random data
-
+
*entries* specifies the total number of directory entries that are created
in the tree. *size* specifies the size occupied by all files together. The
files in *pooldir* are used as a source of directory names and file
contents.
-
+
*seed* is used to initalize the random number generator and can be used to
make the created structure reproducible (provided that the contents of
*pooldir* don't change).
@@ -222,19 +222,19 @@ def populate_dir(path, entries=1000, size=20*1024*1024,
scale = 0.5 * size / sum(file_sizes)
file_sizes = [ int(scale * x) for x in file_sizes ]
file_sizes.append(int(0.5 * size))
-
+
# Special characters for use in filenames
- special_chars = [ chr(x) for x in range(256)
+ special_chars = [ chr(x) for x in range(256)
if x not in (0, ord('/')) ]
def random_name(path):
'''Get random, non-existing file name underneath *path*
-
+
Returns a fully qualified path with a filename chosen from *poolnames*.
'''
while True:
name = poolnames[random.randrange(len(poolnames))]
-
+
# Special characters
len_ = random.randrange(4)
if len_ > 0:
@@ -247,14 +247,14 @@ def populate_dir(path, entries=1000, size=20*1024*1024,
name += s
else:
name += s + poolnames[random.randrange(len(poolnames))]
-
+
fullname = os.path.join(path, name)
if not os.path.lexists(fullname):
break
return fullname
-
-
- #
+
+
+ #
# Step 1: create directory tree
#
dirs = [ path ]
@@ -263,8 +263,8 @@ def populate_dir(path, entries=1000, size=20*1024*1024,
name = random_name(dirs[idx])
os.mkdir(name)
dirs.append(name)
-
-
+
+
#
# Step 2: populate the tree with files
#
@@ -283,7 +283,7 @@ def populate_dir(path, entries=1000, size=20*1024*1024,
dst.write(buf)
size -= len(buf)
files.append(name)
-
+
#
# Step 3: Special files
#
@@ -293,7 +293,7 @@ def populate_dir(path, entries=1000, size=20*1024*1024,
files.append(name)
#
- # Step 4: populate tree with symlinks
+ # Step 4: populate tree with symlinks
#
for _ in range(symlink_cnt):
relative = random.choice((True, False))
@@ -301,7 +301,7 @@ def populate_dir(path, entries=1000, size=20*1024*1024,
idx = random.randrange(len(dirs))
dir_ = dirs[idx]
name = random_name(dir_)
-
+
if existing:
directory = random.choice((True, False))
if directory:
@@ -310,20 +310,20 @@ def populate_dir(path, entries=1000, size=20*1024*1024,
target = files[random.randrange(len(files))]
else:
target = random_name(dirs[random.randrange(len(dirs))])
-
+
if relative:
target = os.path.relpath(target, dir_)
else:
- target = os.path.abspath(target)
-
+ target = os.path.abspath(target)
+
os.symlink(target, name)
-
+
#
# Step 5: Create some hardlinks
#
for _ in range(hardlink_cnt):
samedir = random.choice((True, False))
-
+
target = files[random.randrange(len(files))]
if samedir:
dir_ = os.path.dirname(target)
@@ -332,16 +332,25 @@ def populate_dir(path, entries=1000, size=20*1024*1024,
name = random_name(dir_)
os.link(target, name)
files.append(name)
-
-def get_remote_test_info(name, skipTest):
+
+class NoTestSection(Exception):
+ '''
+ Raised by get_remote_test_info if no matching test
+ section was found.
+ '''
+
+ def __init__(self, reason):
+ self.reason = reason
+
+def get_remote_test_info(name):
authfile = os.path.expanduser('~/.s3ql/authinfo2')
if not os.path.exists(authfile):
- skipTest('No authentication file found.')
+ raise NoTestSection('No authentication file found.')
mode = os.stat(authfile).st_mode
if mode & (stat.S_IRGRP | stat.S_IROTH):
- skipTest("Authentication file has insecure permissions")
+ raise NoTestSection("Authentication file has insecure permissions")
config = configparser.ConfigParser()
config.read(authfile)
@@ -351,7 +360,7 @@ def get_remote_test_info(name, skipTest):
backend_login = config.get(name, 'backend-login')
backend_password = config.get(name, 'backend-password')
except (configparser.NoOptionError, configparser.NoSectionError):
- skipTest("Authentication file does not have %s section" % name)
+ raise NoTestSection("Authentication file does not have %s section" % name)
# Append prefix to make sure that we're starting with an empty bucket
if fs_name[-1] != '/':
@@ -359,5 +368,3 @@ def get_remote_test_info(name, skipTest):
fs_name += 's3ql_test_%d/' % time.time()
return (backend_login, backend_password, fs_name)
-
-
diff --git a/tests/conftest.py b/tests/conftest.py
index 9c2915c..cafc8c3 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -32,11 +32,11 @@ def check_test_output(request, capfd):
(stdout, stderr) = capfd.readouterr()
sys.stdout.write(stdout)
sys.stderr.write(stderr)
-
+
if ('exception' in stderr.lower()
or 'exception' in stdout.lower()):
raise AssertionError('Suspicious output to stderr')
-
+
request.addfinalizer(raise_on_exception_in_out)
@@ -62,14 +62,14 @@ def pytest_addoption(parser):
group._addoption("--installed", action="store_true", default=False,
help="Test the installed package.")
-
+
def pytest_configure(config):
# Enable stdout and stderr analysis, unless output capture is disabled
if config.getoption('capture') != 'no':
global check_test_output
check_test_output = pytest.fixture(autouse=True)(check_test_output)
-
+
logdebug = config.getoption('logdebug')
# If we are running from the S3QL source directory, make sure that we
diff --git a/tests/mock_server.py b/tests/mock_server.py
index 08db0dc..a784425 100644
--- a/tests/mock_server.py
+++ b/tests/mock_server.py
@@ -7,128 +7,197 @@ Copyright (C) Nikolaus Rath <Nikolaus@rath.org>
This program can be distributed under the terms of the GNU GPLv3.
'''
-from http.server import BaseHTTPRequestHandler, _quote_html
+from http.server import BaseHTTPRequestHandler
import re
-import threading
import socketserver
import logging
-from urlparse import urlsplit, parse_qs
+import hashlib
+import urllib.parse
from xml.sax.saxutils import escape as xml_escape
log = logging.getLogger(__name__)
-def start_server(host, port):
- server = HTTPServer((host, port))
- # Initializes .server_name and .server_port
- server.thread = threading.Thread(target=server.serve_forever)
- server.thread.start()
- return server
-
-# Shutdown with:
-# server.shutdown()
-# server.server_close()
+ERROR_RESPONSE_TEMPLATE = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<Error>
+ <Code>%(code)s</Code>
+ <Message>%(message)s</Message>
+ <Resource>%(resource)s</Resource>
+ <RequestId>%(request_id)s</RequestId>
+</Error>
+'''
-class HTTPServer(socketserver.ThreadingTCPServer):
+class StorageServer(socketserver.TCPServer):
- def __init__(self, server_address):
- super().__init__(server_address, RequestHandler, )
+ def __init__(self, request_handler, server_address):
+ super().__init__(server_address, request_handler)
self.data = dict()
self.metadata = dict()
-
-class RequestHandler(BaseHTTPRequestHandler):
+ self.hostname = self.server_address[0]
+ self.port = self.server_address[1]
+
+class ParsedURL:
+ __slots__ = [ 'bucket', 'key', 'params', 'fragment' ]
+
+def parse_url(path):
+ p = ParsedURL()
+ q = urllib.parse.urlsplit(path)
+
+ path = urllib.parse.unquote(q.path)
+
+ assert path[0] == '/'
+ (p.bucket, p.key) = path[1:].split('/', maxsplit=1)
+
+ p.params = urllib.parse.parse_qs(q.query)
+ p.fragment = q.fragment
+
+ return p
+
+class S3RequestHandler(BaseHTTPRequestHandler):
+ '''A request handler implementing a subset of the AWS S3 Interface
+
+ Bucket names are ignored, all keys share the same global
+ namespace.
+ '''
server_version = "MockHTTP"
protocol_version = 'HTTP/1.1'
- meta_header_re = re.compile(r'X-AMZ-Meta-([[:alnum:]-_]+)$',
+ meta_header_re = re.compile(r'X-AMZ-Meta-([a-z0-9_.-]+)$',
re.IGNORECASE)
- xml_ns_prefix = '{http://s3.amazonaws.com/doc/2006-03-01/}'
-
+ hdr_prefix = 'X-AMZ-'
+ xml_ns = 'http://s3.amazonaws.com/doc/2006-03-01/'
+
def log_message(self, format, *args):
log.debug(format, *args)
- def handle_DELETE(self):
- q = urlsplit(self.path)
+ def handle(self):
+ # Ignore exceptions resulting from the client closing
+ # the connection.
+ try:
+ return super().handle()
+ except ValueError as exc:
+ if exc.args == ('I/O operation on closed file.',):
+ pass
+ else:
+ raise
+ except BrokenPipeError:
+ pass
+
+ def do_DELETE(self):
+ q = parse_url(self.path)
try:
- del self.server.data[q.path]
- del self.server.metadata[q.path]
+ del self.server.data[q.key]
+ del self.server.metadata[q.key]
except KeyError:
- self.send_error(404)
+ self.send_error(404, code='NoSuchKey', resource=q.key)
return
else:
self.send_response(204)
self.end_headers()
- def handle_PUT(self):
+ def _check_encoding(self):
encoding = self.headers['Content-Encoding']
- len_ = self.headers['Content-Length']
- if not len_ or (encoding and encoding != 'identity'):
- self.send_error(415)
+ if 'Content-Length' not in self.headers:
+ self.send_error(400, message='Missing Content-Length',
+ code='MissingContentLength')
return
- len_ = int(len_)
+ elif encoding and encoding != 'identity':
+ self.send_error(501, message='Unsupport encoding',
+ code='NotImplemented')
+ return
+
+ return int(self.headers['Content-Length'])
- q = urlsplit(self.path)
+ def do_PUT(self):
+ len_ = self._check_encoding()
+ q = parse_url(self.path)
meta = dict()
- for (name, value) in self.headers.items:
- hit = self.meta_header_re.match(name)
+ for (name, value) in self.headers.items():
+ hit = self.meta_header_re.search(name)
if hit:
meta[hit.group(1)] = value
- src = headers.get('x-amz-copy-source')
- if src:
- hit = re.match('^/([[:alnum:]]+)/(.+)$', src)
+ src = self.headers.get(self.hdr_prefix + 'copy-source')
+ if src and len_:
+ self.send_error(400, message='Upload and copy are mutually exclusive',
+ code='UnexpectedContent')
+ return
+ elif src:
+ hit = re.match('^/([a-z0-9._-]+)/(.+)$', src)
if not hit:
-
- # TODO: etag
-
- self.server.metadata[q.path] = meta
- self.server.data[q.path] = self.rfile.read(len_)
+ self.send_error(400, message='Cannot parse copy-source',
+ code='InvalidArgument')
+ return
+
+ metadata_directive = self.headers.get(self.hdr_prefix + 'metadata-directive',
+ 'COPY')
+ if metadata_directive not in ('COPY', 'REPLACE'):
+ self.send_error(400, message='Invalid metadata directive',
+ code='InvalidArgument')
+ return
+ src = hit.group(2)
+ try:
+ data = self.server.data[src]
+ self.server.data[q.key] = data
+ if metadata_directive == 'COPY':
+ self.server.metadata[q.key] = self.server.metadata[src]
+ else:
+ self.server.metadata[q.key] = meta
+ except KeyError:
+ self.send_error(404, code='NoSuchKey', resource=src)
+ else:
+ data = self.rfile.read(len_)
+ self.server.metadata[q.key] = meta
+ self.server.data[q.key] = data
+
+ md5 = hashlib.md5()
+ md5.update(data)
self.send_response(201)
+ self.send_header('ETag', '"%s"' % md5.hexdigest())
+ self.send_header('Content-Length', '0')
self.end_headers()
def handle_expect_100(self):
if self.command == 'PUT':
- encoding = self.headers['Content-Encoding']
- len_ = self.headers['Content-Length']
- if not len_ or (encoding and encoding != 'identity'):
- self.send_error(415)
- return False
-
+ self._check_encoding()
+
self.send_response_only(100)
self.end_headers()
return True
def do_GET(self):
- q = urlsplit(self.path)
-
- if q.path == '/':
+ q = parse_url(self.path)
+ if not q.key:
return self.do_list(q)
try:
- data = self.server.data[q.path]
- meta = self.server.metadata[q.path]
+ data = self.server.data[q.key]
+ meta = self.server.metadata[q.key]
except KeyError:
- self.send_error(404)
+ self.send_error(404, code='NoSuchKey', resource=q.key)
return
-
+
self.send_response(200)
self.send_header("Content-Type", 'application/octet-stream')
self.send_header("Content-Length", str(len(data)))
- for tup in meta.items():
- self.send_header('X-AMZ-Meta-%s: %s' % tup)
+ for (name, value) in meta.items():
+ self.send_header(self.hdr_prefix + 'Meta-%s' % name, value)
+ md5 = hashlib.md5()
+ md5.update(data)
+ self.send_header('ETag', '"%s"' % md5.hexdigest())
self.end_headers()
self.wfile.write(data)
def do_list(self, q):
- qs = parse_qs(q.query)
- marker = qs.get('marker', None)
- prefix = qs.get('prefix', '')
- max_keys = qs.get('max_keys', 1000)
+ marker = q.params['marker'][0] if 'marker' in q.params else None
+ max_keys = int(q.params['max_keys'][0]) if 'max_keys' in q.params else 1000
+ prefix = q.params['prefix'][0] if 'prefix' in q.params else ''
resp = ['<?xml version="1.0" encoding="UTF-8"?>',
- '<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">',
+ '<ListBucketResult xmlns="%s">' % self.xml_ns,
'<MaxKeys>%d</MaxKeys>' % max_keys,
'<IsTruncated>false</IsTruncated>' ]
-
+
count = 0
for key in self.server.data:
if not key.startswith(prefix):
@@ -143,48 +212,69 @@ class RequestHandler(BaseHTTPRequestHandler):
resp.append('</ListBucketResult>')
body = '\n'.join(resp).encode()
-
+
self.send_response(200)
self.send_header("Content-Type", 'text/xml')
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
-
-
+
def do_HEAD(self):
- q = urlsplit(self.path)
+ q = parse_url(self.path)
try:
- meta = self.server.metadata[q.path]
- data = self.server.data[q.path]
+ meta = self.server.metadata[q.key]
+ data = self.server.data[q.key]
except KeyError:
- self.send_error(404)
+ self.send_error(404, code='NoSuchKey', resource=q.key)
return
-
+
self.send_response(200)
self.send_header("Content-Type", 'application/octet-stream')
self.send_header("Content-Length", str(len(data)))
- for tup in meta.items():
- self.send_header('X-AMZ-Meta-%s: %s' % tup)
+ for (name, value) in meta.items():
+ self.send_header(self.hdr_prefix + 'Meta-%s' % name, value)
self.end_headers()
- def send_error(self, code, message=None):
- # Overwritten to not close connection on errors and provide
- # content-length
- try:
- shortmsg, longmsg = self.responses[code]
- except KeyError:
- shortmsg, longmsg = '???', '???'
- if message is None:
- message = shortmsg
- explain = longmsg
- self.log_error("code %d, message %s", code, message)
- # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201)
- content = (self.error_message_format % {'code': code, 'message': _quote_html(message),
- 'explain': explain}).encode('utf-8', 'replace')
- self.send_response(code, message)
- self.send_header("Content-Type", self.error_content_type)
+ def send_error(self, status, message=None, code='', resource='',
+ extra_headers=None):
+
+ if not message:
+ try:
+ (_, message) = self.responses[status]
+ except KeyError:
+ message = 'Unknown'
+
+ self.log_error("code %d, message %s", status, message)
+ content = (ERROR_RESPONSE_TEMPLATE %
+ {'code': code,
+ 'message': xml_escape(message),
+ 'request_id': 42,
+ 'resource': xml_escape(resource)}).encode('utf-8', 'replace')
+ self.send_response(status, message)
+ self.send_header("Content-Type", 'text/xml; charset="utf-8"')
self.send_header("Content-Length", str(len(content)))
+ if extra_headers:
+ for (name, value) in extra_headers.items():
+ self.send_header(name, value)
self.end_headers()
- if self.command != 'HEAD' and code >= 200 and code not in (204, 304):
+ if self.command != 'HEAD' and status >= 200 and status not in (204, 304):
self.wfile.write(content)
-
+
+
+class GSRequestHandler(S3RequestHandler):
+ '''A request handler implementing a subset of the Google Storage API.
+
+ Bucket names are ignored, all keys share the same global namespace.
+ '''
+
+ meta_header_re = re.compile(r'x-goog-meta-([a-z0-9_.-]+)$',
+ re.IGNORECASE)
+ hdr_prefix = 'x-goog-'
+ xml_ns = 'http://doc.s3.amazonaws.com/2006-03-01'
+
+#: A list of the available mock request handlers with
+#: corresponding storage urls
+handler_list = [ (S3RequestHandler, 's3c://%(host)s:%(port)d/s3ql_test'),
+
+ # Special syntax only for testing against mock server
+ (GSRequestHandler, 'gs://!unittest!%(host)s:%(port)d/s3ql_test') ]
diff --git a/tests/t1_backends.py b/tests/t1_backends.py
index 93222a2..a6c13e5 100755
--- a/tests/t1_backends.py
+++ b/tests/t1_backends.py
@@ -12,643 +12,1048 @@ if __name__ == '__main__':
import sys
sys.exit(pytest.main([__file__] + sys.argv[1:]))
-from s3ql.backends import local, s3, gs, s3c, swift, rackspace, swiftks
+import mock_server
from s3ql import backends
+from s3ql.logging import logging
+from s3ql.backends.local import Backend as LocalBackend
+from s3ql.backends.gs import Backend as GSBackend
from s3ql.backends.common import (ChecksumError, ObjectNotEncrypted, NoSuchObject,
- BetterBackend, get_ssl_context, AuthenticationError, AuthorizationError,
- DanglingStorageURLError, MalformedObjectError, DecryptFilter, DecompressFilter)
-from s3ql.common import BUFSIZE
-from common import get_remote_test_info
+ BetterBackend, AuthenticationError, AuthorizationError, DanglingStorageURLError,
+ MalformedObjectError)
+from s3ql.backends.s3c import BadDigestError, OperationAbortedError, HTTPError
+from s3ql.common import BUFSIZE, get_ssl_context
+from contextlib import ExitStack
+from common import get_remote_test_info, NoTestSection, catch_logmsg
import s3ql.backends.common
from argparse import Namespace
-import os
import tempfile
+import re
+import functools
import time
-import unittest
import pytest
+from pytest import raises as assert_raises
+import shutil
import struct
+import threading
-RETRY_DELAY = 1
-
-@pytest.yield_fixture(params=('local', 's3', 'gs', 's3c', 'swift',
- 'rackspace', 'swiftks'))
-def plain_backend(request):
- backend_name = request.param
- backend_module = getattr(backends, backend_name)
- backend_class = backend_module.Backend
- if backend_name == 'local':
- backend_dir = tempfile.mkdtemp(prefix='s3ql-backend-')
- backend = backend_class('local://' + backend_dir, None, None)
- else:
- options = Namespace()
- options.no_ssl = False
- options.ssl_ca_path = None
+log = logging.getLogger(__name__)
+empty_set = set()
- (backend_login, backend_password,
- fs_name) = get_remote_test_info(backend_name + '-test', pytest.skip)
-
- backend = backend_class(fs_name, backend_login, backend_password,
- ssl_context=get_ssl_context(options))
+class BackendWrapper:
- try:
- backend.fetch('empty_object')
- except DanglingStorageURLError:
- pytest.skip('Bucket %s does not exist' % fs_name)
- except AuthorizationError:
- pytest.skip('No permission to access %s' % fs_name)
- except AuthenticationError:
- pytest.skip('Unable to access %s, invalid credentials or skewed '
- 'system clock?' % fs_name)
- except NoSuchObject:
+ def __init__(self, name, retry_time=0):
+ self.name = name
+ self.retry_time = retry_time
+ self.backend = self._init()
+
+ self.orig_prefix = self.backend.prefix
+ self.prefix_counter = 0
+
+ def _init(self):
+ '''Return backend instance'''
pass
- else:
- pytest.skip('Test bucket not empty')
-
- try:
- yield backend
- finally:
- backend.clear()
- backend.close()
- if backend_name == 'local':
- os.rmdir(backend_dir)
-
-@pytest.fixture(params=('plain', 'aes+lzma', 'zlib', 'bzip2', 'lzma'))
-def backend(request, plain_backend):
- arg = request.param
- if arg == 'plain':
+ def cleanup(self):
+ '''Cleanup backend'''
+ self.backend.close()
+
+ def reset(self):
+ '''Prepare backend for reuse'''
+
+ # "clear" the backend by selecting a different prefix for every
+ # test (actually deleting all objects would mean that we have to
+ # wait for propagation delays)
+ self.backend.prefix = '%s%3d/' % (self.orig_prefix,
+ self.prefix_counter)
+ self.prefix_counter += 1
+
+ def __str__(self):
+ return self.name
+
+class LocalBackendWrapper(BackendWrapper):
+
+ def __init__(self):
+ super().__init__('local')
+
+ def _init(self):
+ self.backend_dir = tempfile.mkdtemp(prefix='s3ql-backend-')
+ return backends.local.Backend('local://' + self.backend_dir, None, None)
+
+ def cleanup(self):
+ super().cleanup()
+ shutil.rmtree(self.backend_dir)
+
+class MockBackendWrapper(BackendWrapper):
+ def __init__(self, request_handler, storage_url):
+ backend_name = re.match(r'^([a-zA-Z0-9]+)://', storage_url).group(1)
+ self.backend_class = backends.prefix_map[backend_name]
+ self.request_handler = request_handler
+ self.may_temp_fail = False
+ self.storage_url = storage_url
+ super().__init__('mock_' + backend_name)
+
+ def _init(self):
+ self.server = mock_server.StorageServer(self.request_handler, ('localhost', 0))
+ self.thread = threading.Thread(target=self.server.serve_forever)
+ self.thread.daemon = True
+ self.thread.start()
+ storage_url = self.storage_url % { 'host': self.server.server_address[0],
+ 'port': self.server.server_address[1] }
+ backend = self.backend_class(storage_url, 'joe', 'swordfish')
+
+ # Enable OAuth when using Google Backend
+ if isinstance(backend, GSBackend):
+ backend.use_oauth2 = True
+ backend.hdr_prefix = 'x-goog-' # Normally set in __init__
+ backend.access_token[backend.password] = 'foobar'
+
+ # Mock server should not have temporary failures by default
+ is_temp_failure = backend.is_temp_failure
+ @functools.wraps(backend.is_temp_failure)
+ def wrap(exc):
+ if self.may_temp_fail:
+ return is_temp_failure(exc)
+ else:
+ return False
+ backend.is_temp_failure = wrap
+ return backend
+
+ def cleanup(self):
+ super().cleanup()
+ self.server.server_close()
+ self.server.shutdown()
+
+
+class RemoteBackendWrapper(BackendWrapper):
+
+ def __init__(self, backend_name, backend_class, ssl_context):
+ self.class_ = backend_class
+ self.ssl_context = ssl_context
+ super().__init__(backend_name, retry_time=600)
+
+ def _init(self):
+ # May raise NoTestSection
+ (login, password, storage_url) = get_remote_test_info(self.name + '-test')
+
+ backend = self.class_(storage_url, login, password,
+ ssl_context=self.ssl_context)
+ try:
+ backend.fetch('empty_object')
+ except DanglingStorageURLError:
+ raise SystemExit('%s does not exist' % storage_url)
+ except AuthorizationError:
+ raise SystemExit('No permission to access %s' % storage_url)
+ except AuthenticationError:
+ raise SystemExit('Unable to access %s, invalid credentials' % storage_url)
+ except NoSuchObject:
+ pass
+ else:
+ raise SystemExit('%s not empty' % storage_url)
+ return backend
+
+ def cleanup(self):
+ self.backend.clear()
+ self.backend.close()
+
+_backend_wrappers = []
+# It'd be nice if we could use the setup_module hook instead, but
+# unfortunately that gets executed *after* pytest_generate_tests.
+def _init_wrappers():
+ '''Get list of *BackendWrapper* instances for all available backends'''
+
+ # Local backend
+ _backend_wrappers.append(LocalBackendWrapper())
+
+ # Backends talking to local mock servers
+ for (request_handler, storage_url) in mock_server.handler_list:
+ _backend_wrappers.append(MockBackendWrapper(request_handler, storage_url))
+
+ # Backends talking to actual remote servers (if available)
+ options = Namespace()
+ options.no_ssl = False
+ options.ssl_ca_path = None
+ ssl_context = get_ssl_context(options)
+ for (backend_name, backend_class) in backends.prefix_map.items():
+ if backend_name == 'local': # local backend has already been handled
+ continue
+
+ try:
+ bw = RemoteBackendWrapper(backend_name, backend_class, ssl_context)
+ except NoTestSection as exc:
+ log.info('Not doing remote tests for %s backend: %s',
+ backend_name, exc.reason)
+ continue
+ _backend_wrappers.append(bw)
+
+def teardown_module(self):
+ '''Clean-up all backend wrappers'''
+
+ # Use ExitStack to ensure that all wrappers are cleaned up,
+ # even if a cleanup raises an exception
+ with ExitStack() as stack:
+ for w in _backend_wrappers:
+ stack.callback(w.cleanup)
+
+@pytest.fixture()
+def backend_wrapper(request):
+ bw = request.param
+ request.addfinalizer(bw.reset)
+ return request.param
+
+@pytest.fixture()
+def retry_time(backend_wrapper):
+ return backend_wrapper.retry_time
+
+def pytest_generate_tests(metafunc):
+ if not _backend_wrappers:
+ _init_wrappers()
+
+ if 'backend' in metafunc.fixturenames:
+ assert 'compenc_kind' in metafunc.fixturenames
+ assert 'backend_wrapper' in metafunc.fixturenames
+
+ if getattr(metafunc.function, 'require_encryption', False):
+ compenc_kind = ('aes+lzma', 'aes')
+ elif getattr(metafunc.function, 'require_compenc', False):
+ compenc_kind = ('aes', 'aes+lzma', 'lzma', 'zlib', 'bzip2')
+ else:
+ compenc_kind = ('plain', 'aes', 'aes+lzma', 'lzma', 'zlib', 'bzip2')
+ metafunc.parametrize("compenc_kind", compenc_kind)
+
+ if hasattr(metafunc.function, 'wrapper_filter'):
+ wrappers = [ x for x in _backend_wrappers
+ if metafunc.function.wrapper_filter(x) ]
+ else:
+ wrappers = _backend_wrappers
+
+ # Needs to be function scope, otherwise we cannot assign
+ # different parametrizations to different test functions
+ # (cf. https://bitbucket.org/hpk42/pytest/issue/531/)
+ metafunc.parametrize("backend_wrapper", wrappers, indirect=True,
+ ids=[ str(w) for w in wrappers ])
+
+@pytest.fixture()
+def backend(compenc_kind, backend_wrapper):
+ plain_backend = backend_wrapper.backend
+ if compenc_kind == 'plain':
return plain_backend
- elif arg == 'aes+lzma':
+ elif compenc_kind == 'aes+lzma':
return BetterBackend(b'schlurz', ('lzma', 6), plain_backend)
+ elif compenc_kind == 'aes':
+ return BetterBackend(b'schlurz', (None, 6), plain_backend)
else:
- return BetterBackend(None, (arg, 6), plain_backend)
+ return BetterBackend(None, (compenc_kind, 6), plain_backend)
-@pytest.fixture()
-def retries(request, plain_backend):
- if isinstance(plain_backend, local.Backend):
- return 0
- else:
- return 90
-
-@pytest.fixture()
-def retry_fn(request, plain_backend):
- if isinstance(plain_backend, local.Backend):
- return lambda x, *a: x()
+def require_plain_backend(class_):
+ '''Require plain backend of type *class*_
- def retry(fn, *exceptions):
- tries = 0
- while True:
- try:
- return fn()
- except Exception as exc:
- if not isinstance(exc, exceptions):
- raise
- if tries >= 90:
- raise
- tries += 1
- time.sleep(RETRY_DELAY)
- else:
- break
-
- return retry
+ Returns a decorator that marks the test function for being
+ called only with plain backends of the specific class.
+ '''
+
+ def decorator(test_fn):
+ assert not hasattr(test_fn, 'wrapper_filter')
+ test_fn.wrapper_filter = lambda x: isinstance(x.backend, class_)
+ return test_fn
+ return decorator
+
+def require_backend_wrapper(class_):
+ '''Require backend wrapper of type *class*_
+
+ Returns a decorator that marks the test function for being
+ called only with backends whose wrappers are instances
+ of *class_*.
+ '''
+
+ def decorator(test_fn):
+ assert not hasattr(test_fn, 'wrapper_filter')
+ test_fn.wrapper_filter = lambda x: isinstance(x, class_)
+ return test_fn
+ return decorator
+
+def require_wrapper(filter_fn):
+ def decorator(test_fn):
+ assert not hasattr(test_fn, 'wrapper_filter')
+ test_fn.wrapper_filter = filter_fn
+ return test_fn
+ return decorator
+
+def require_immediate_consistency(test_fn):
+ '''Require immediate consistency
+
+ Decorator. Marks the function to be called only with backends
+ offering immediate consistency.
+ '''
-name_counter = [0]
-def newname():
+ assert not hasattr(test_fn, 'wrapper_filter')
+ test_fn.wrapper_filter = (lambda x: x.retry_time == 0)
+ return test_fn
+
+def require_compression_or_encryption(test_fn):
+ '''Require compressing or encrypting backend
+
+ Decorator. Marks the function to be called only with backends
+ that encrypt or compress (or both) their contents.
+ '''
+
+ test_fn.require_compenc = True
+ return test_fn
+
+def require_encryption(test_fn):
+ '''Require encrypting backend
+
+ Decorator. Marks the function to be called only with backends
+ that encrypt their contents.
+ '''
+
+ test_fn.require_encryption = True
+ return test_fn
+
+def newname(name_counter=[0]):
'''Return random, unique string'''
name_counter[0] += 1
return "s3ql/<tag=%d>/!sp ace_'quote\":_&end\\" % name_counter[0]
-
+
def newvalue():
return newname().encode()
-def test_write(backend, retry_fn):
+def fetch_object(backend, key, retry_time, sleep_time=1):
+ '''Read data and metadata for *key* from *backend*
+
+ If `NoSuchObject` exception is encountered, retry for
+ up to *retry_time* seconds.
+ '''
+ waited=0
+ while True:
+ try:
+ return backend.fetch(key)
+ except NoSuchObject:
+ if waited >= retry_time:
+ raise
+ time.sleep(sleep_time)
+ waited += sleep_time
+
+def lookup_object(backend, key, retry_time, sleep_time=1):
+ '''Read metadata for *key* from *backend*
+
+ If `NoSuchObject` exception is encountered, retry for
+ up to *retry_time* seconds.
+ '''
+ waited=0
+ while True:
+ try:
+ return backend.lookup(key)
+ except NoSuchObject:
+ if waited >= retry_time:
+ raise
+ time.sleep(sleep_time)
+ waited += sleep_time
+
+def assert_in_index(backend, keys, retry_time, sleep_time=1):
+ '''Assert that *keys* will appear in index
+
+ Raises assertion error if *keys* do not show up within
+ *retry_time* seconds.
+ '''
+ waited=0
+ keys = set(keys) # copy
+ while True:
+ index = set(backend.list())
+ if not keys - index:
+ return
+ elif waited >= retry_time:
+ assert keys - index == empty_set
+ time.sleep(sleep_time)
+ waited += sleep_time
+
+def assert_not_in_index(backend, keys, retry_time, sleep_time=1):
+ '''Assert that *keys* will disappear from index
+
+ Raises assertion error if *keys* do not disappear within
+ *retry_time* seconds.
+ '''
+ waited=0
+ keys = set(keys) # copy
+ while True:
+ index = set(backend.list())
+ if keys - index == keys:
+ return
+ elif waited >= retry_time:
+ assert keys - index == keys
+ time.sleep(sleep_time)
+ waited += sleep_time
+
+def assert_not_readable(backend, key, retry_time, sleep_time=1):
+ '''Assert that *key* does not exist in *backend*
+
+ Asserts that a `NoSuchObject` exception will be raised when trying to read
+ the object after at most *retry_time* seconds.
+ '''
+ waited=0
+ while True:
+ try:
+ backend.fetch(key)
+ except NoSuchObject:
+ return
+ if waited >= retry_time:
+ pytest.fail('object %s still present in backend' % key)
+ time.sleep(sleep_time)
+ waited += sleep_time
+
+def test_read_write(backend, retry_time):
key = newname()
value = newvalue()
metadata = { 'jimmy': 'jups@42' }
- with pytest.raises(NoSuchObject):
- backend.lookup(key)
-
- with pytest.raises(NoSuchObject):
- backend.fetch(key)
-
- with backend.open_write(key, metadata) as fh:
+ assert key not in backend
+ assert_raises(NoSuchObject, backend.lookup, key)
+ assert_raises(NoSuchObject, backend.fetch, key)
+
+ def do_write(fh):
fh.write(value)
+ backend.perform_write(do_write, key, metadata)
+
+ assert_in_index(backend, [key], retry_time)
+ (value2, metadata2) = fetch_object(backend, key, retry_time)
+
+ assert value == value2
+ assert metadata == metadata2
+ assert lookup_object(backend, key, retry_time) == metadata
+
+def test_list(backend, retry_time):
+ keys = ([ 'prefixa' + newname() for dummy in range(6) ]
+ + [ 'prefixb' + newname() for dummy in range(6) ])
+ values = [ newvalue() for dummy in range(12) ]
+
+ assert set(backend.list()) == empty_set
+ for i in range(12):
+ backend[keys[i]] = values[i]
+ assert_in_index(backend, keys, retry_time)
- def read():
+ assert set(backend.list('prefixa')) == set(keys[:6])
+ assert set(backend.list('prefixb')) == set(keys[6:])
+ assert set(backend.list('prefixc')) == empty_set
+
+@require_immediate_consistency
+def test_readslowly(backend):
+ key = newname()
+ value = newvalue()
+ metadata = { 'jimmy': 'jups@42' }
+
+ backend.store(key, value, metadata)
+
+ s3ql.backends.common.BUFSIZE = 1
+ try:
with backend.open_read(key) as fh:
- return (fh.read(), fh.metadata)
- (value2, metadata2) = retry_fn(read, NoSuchObject)
+ # Force slow reading from underlying layer
+ if hasattr(fh, 'fh'):
+ def read_slowly(size, *, real_read=fh.fh.read):
+ return real_read(1)
+ fh.fh.read = read_slowly
+
+ buf = []
+ while True:
+ buf.append(fh.read(1))
+ if not buf[-1]:
+ break
+ value2 = b''.join(buf)
+ metadata2 = fh.metadata
+ finally:
+ s3ql.backends.common.BUFSIZE = BUFSIZE
assert value == value2
assert metadata == metadata2
- assert backend[key] == value
- assert backend.lookup(key) == metadata
-
-class BackendTestsMixin(object):
+def test_delete(backend, retry_time):
+ key = newname()
+ value = newvalue()
- def newname(self):
- self.name_cnt += 1
- # Include special characters
- return "s3ql/<tag=%d>/!sp ace_'quote\":_&end\\" % self.name_cnt
+ backend[key] = value
- def newvalue(self):
- return self.newname().encode()
+ # Wait for object to become visible
+ assert_in_index(backend, [key], retry_time)
+ fetch_object(backend, key, retry_time)
- def retry(self, fn, *exceptions):
- tries = 0
- while True:
- try:
- return fn()
- except Exception as exc:
- if not isinstance(exc, exceptions):
- raise
- if tries >= self.retries:
- raise
- tries += 1
- time.sleep(RETRY_DELAY)
- else:
- break
-
- def test_write(self):
- key = self.newname()
- value = self.newvalue()
- metadata = { 'jimmy': 'jups@42' }
+ # Delete it
+ del backend[key]
- self.assertRaises(NoSuchObject, self.backend.lookup, key)
- self.assertRaises(NoSuchObject, self.backend.fetch, key)
+ # Make sure that it's truly gone
+ assert_not_in_index(backend, [key], retry_time)
+ assert_not_readable(backend, key, retry_time)
- with self.backend.open_write(key, metadata) as fh:
- fh.write(value)
+def test_delete_multi(backend, retry_time):
+ keys = [ newname() for _ in range(30) ]
+ value = newvalue()
- def read():
- with self.backend.open_read(key) as fh:
- return (fh.read(), fh.metadata)
- (value2, metadata2) = self.retry(read, NoSuchObject)
+ # Create objects
+ for key in keys:
+ backend[key] = value
+
+ # Wait for them
+ assert_in_index(backend, keys, retry_time)
+ for key in keys:
+ fetch_object(backend, key, retry_time)
+
+ # Delete half of them
+ # We don't use force=True but catch the exemption to increase the
+ # chance that some existing objects are not deleted because of the
+ # error.
+ to_delete = keys[::2]
+ to_delete.insert(7, 'not_existing')
+ try:
+ backend.delete_multi(to_delete)
+ except NoSuchObject:
+ pass
- self.assertEqual(value, value2)
- self.assertEqual(metadata, metadata2)
- self.assertEqual(self.backend[key], value)
- self.assertEqual(self.backend.lookup(key), metadata)
+ # Without full consistency, deleting an non-existing object
+ # may not give an error
+ assert retry_time or len(to_delete) > 0
+ deleted = set(keys[::2]) - set(to_delete)
+ assert len(deleted) > 0
+ remaining = set(keys) - deleted
- def test_readslowly(self):
- key = self.newname()
- value = self.newvalue()
- metadata = { 'jimmy': 'jups@42' }
+ assert_not_in_index(backend, deleted, retry_time)
+ for key in deleted:
+ assert_not_readable(backend, key, retry_time)
- with self.backend.open_write(key, metadata) as fh:
- fh.write(value)
+ assert_in_index(backend, remaining, retry_time)
+ for key in remaining:
+ fetch_object(backend, key, retry_time)
- def read():
- buf = []
- with self.backend.open_read(key) as fh:
- # Force slow reading from underlying layer
- if isinstance(fh, (DecryptFilter, DecompressFilter)):
- real_read = fh.fh.read
- def read_slowly(size):
- return real_read(1)
- fh.fh.read = read_slowly
- while True:
- buf.append(fh.read(1))
- if not buf[-1]:
- break
-
- return (b''.join(buf), fh.metadata)
+def test_clear(backend, retry_time):
+ keys = [ newname() for _ in range(5) ]
+ value = newvalue()
- try:
- s3ql.backends.common.BUFSIZE = 1
- (value2, metadata2) = self.retry(read, NoSuchObject)
- finally:
- s3ql.backends.common.BUFSIZE = BUFSIZE
-
- self.assertEqual(value, value2)
- self.assertEqual(metadata, metadata2)
-
- def test_setitem(self):
- key = self.newname()
- value = self.newvalue()
- metadata = { 'jimmy': 'jups@42' }
-
- self.assertRaises(NoSuchObject, self.backend.lookup, key)
- self.assertRaises(NoSuchObject, self.backend.__getitem__, key)
-
- with self.backend.open_write(key, metadata) as fh:
- fh.write(self.newvalue())
-
- def read():
- with self.backend.open_read(key) as fh:
- return fh.read()
- self.retry(read, NoSuchObject)
-
- self.backend[key] = value
-
- def reread():
- with self.backend.open_read(key) as fh:
- value2 = fh.read()
-
- self.assertEqual(value, value2)
- self.assertEqual(fh.metadata, None)
- self.assertEqual(self.backend.lookup(key), None)
- self.retry(reread, NoSuchObject, AssertionError)
-
- def test_contains(self):
- key = self.newname()
- value = self.newvalue()
-
- self.assertFalse(key in self.backend)
- self.backend[key] = value
-
- self.retry(lambda: self.assertTrue(key in self.backend),
- AssertionError)
-
- def test_delete(self):
- key = self.newname()
- value = self.newvalue()
-
- self.backend[key] = value
-
- self.retry(lambda: self.assertTrue(key in self.backend),
- AssertionError)
-
- del self.backend[key]
-
- self.retry(lambda: self.assertFalse(key in self.backend),
- AssertionError)
-
-
- def test_delete_multi(self):
- keys = [ self.newname() for _ in range(5) ]
- value = self.newvalue()
-
- for key in keys:
- self.backend[key] = value
- for key in keys:
- self.retry(lambda: self.assertTrue(key in self.backend), AssertionError)
-
- tmp = keys[:2]
- self.backend.delete_multi(tmp)
- self.assertEqual(len(tmp), 0)
-
- for key in keys[:2]:
- self.retry(lambda: self.assertFalse(key in self.backend),
- AssertionError)
-
- for key in keys[2:]:
- self.retry(lambda: self.assertTrue(key in self.backend), AssertionError)
-
-
- def test_delete_multi2(self):
- keys = [ self.newname() for _ in range(5) ]
- non_existing = self.newname()
- value = self.newvalue()
-
- for key in keys:
- self.backend[key] = value
- for key in keys:
- self.retry(lambda: self.assertTrue(key in self.backend), AssertionError)
-
- tmp = keys[:2]
- tmp.insert(1, non_existing)
- try:
- # We don't use force=True but catch the exemption to increase the
- # chance that some existing objects are not deleted because of the
- # error.
- self.backend.delete_multi(tmp)
- except NoSuchObject:
- pass
-
- for key in keys[:2]:
- if key in tmp:
- self.retry(lambda: self.assertTrue(key in self.backend),
- AssertionError)
- else:
- self.retry(lambda: self.assertTrue(key not in self.backend),
- AssertionError)
-
- for key in keys[2:]:
- self.retry(lambda: self.assertTrue(key in self.backend), AssertionError)
-
-
- def test_clear(self):
- key1 = self.newname()
- key2 = self.newname()
- self.backend[key1] = self.newvalue()
- self.backend[key2] = self.newvalue()
-
- def check1():
- self.assertTrue(key1 in self.backend)
- self.assertTrue(key2 in self.backend)
- self.assertEqual(len(list(self.backend)), 2)
- self.retry(check1, AssertionError)
-
- self.backend.clear()
+ # Create objects
+ for key in keys:
+ backend[key] = value
- def check2():
- self.assertTrue(key1 not in self.backend)
- self.assertTrue(key2 not in self.backend)
- self.assertEqual(len(list(self.backend)), 0)
- self.retry(check2, AssertionError)
-
-
- def test_list(self):
-
- keys = [ self.newname() for dummy in range(12) ]
- values = [ self.newvalue() for dummy in range(12) ]
- for i in range(12):
- self.backend[keys[i]] = values[i]
-
- self.retry(lambda: self.assertEqual(sorted(self.backend.list()), sorted(keys)),
- AssertionError)
-
- def test_copy(self):
-
- key1 = self.newname()
- key2 = self.newname()
- value = self.newvalue()
- self.assertRaises(NoSuchObject, self.backend.lookup, key1)
- self.assertRaises(NoSuchObject, self.backend.lookup, key2)
-
- self.backend.store(key1, value)
-
- self.retry(lambda: self.assertTrue(key1 in self.backend),
- AssertionError)
- self.retry(lambda: self.assertEqual(self.backend[key1], value),
- NoSuchObject)
-
- self.backend.copy(key1, key2)
-
- self.retry(lambda: self.assertTrue(key2 in self.backend),
- AssertionError)
- self.retry(lambda: self.assertEqual(self.backend[key2], value),
- NoSuchObject)
-
- def test_rename(self):
-
- key1 = self.newname()
- key2 = self.newname()
- value = self.newvalue()
- self.assertRaises(NoSuchObject, self.backend.lookup, key1)
- self.assertRaises(NoSuchObject, self.backend.lookup, key2)
-
- self.backend.store(key1, value)
-
- self.retry(lambda: self.assertTrue(key1 in self.backend),
- AssertionError)
- self.retry(lambda: self.assertEqual(self.backend[key1], value),
- NoSuchObject)
-
- self.backend.rename(key1, key2)
-
- def check2():
- self.assertTrue(key2 in self.backend)
- self.assertTrue(key1 not in self.backend)
- self.assertRaises(NoSuchObject, self.backend.lookup, key1)
- self.retry(check2, AssertionError, NoSuchObject)
- self.retry(lambda: self.assertEqual(self.backend[key2], value),
- NoSuchObject)
-
-
-class BackendTestTemplate(BackendTestsMixin):
-
- def setUp2(self, backend_class, backend_fs_name):
-
- options = Namespace()
- options.no_ssl = False
- options.ssl_ca_path = None
-
- (backend_login, backend_password,
- fs_name) = get_remote_test_info(backend_fs_name, self.skipTest)
-
- self.backend = backend_class(fs_name, backend_login, backend_password,
- ssl_context=get_ssl_context(options))
+ # Wait for them
+ assert_in_index(backend, keys, retry_time)
+ for key in keys:
+ fetch_object(backend, key, retry_time)
- try:
- self.backend.fetch('empty_object')
- except DanglingStorageURLError:
- raise unittest.SkipTest('Bucket %s does not exist' % fs_name) from None
- except AuthorizationError:
- raise unittest.SkipTest('No permission to access %s' % fs_name) from None
- except AuthenticationError:
- raise unittest.SkipTest('Unable to access %s, invalid credentials or skewed '
- 'system clock?' % fs_name) from None
- except NoSuchObject:
- pass
- else:
- raise unittest.SkipTest('Test bucket not empty') from None
+ # Delete everything
+ backend.clear()
- def tearDown(self):
- self.backend.clear()
- self.backend.close()
+ assert_not_in_index(backend, keys, retry_time)
+ for key in keys:
+ assert_not_readable(backend, key, retry_time)
-
-# Dynamically generate tests for other backends
-for backend_display_name in ('Swift', 'S3', 'SwiftKS', 'Rackspace', 'GS', 'S3C'):
- backend_name = backend_display_name.lower()
- backend_class = globals()[backend_name].Backend
- def setUp(self, backend_name=backend_name,
- backend_class=backend_class):
- self.name_cnt = 0
- self.retries = 90
- self.setUp2(backend_class, backend_name + '-test')
- test_class_name = backend_display_name + 'Tests'
- globals()[test_class_name] = type(test_class_name,
- (BackendTestTemplate, unittest.TestCase),
- { 'setUp': setUp })
-
-
-class LocalTests(BackendTestsMixin, unittest.TestCase):
-
- def setUp(self):
- self.name_cnt = 0
- self.backend_dir = tempfile.mkdtemp(prefix='s3ql-backend-')
- self.backend = local.Backend('local://' + self.backend_dir, None, None)
- self.retries = 0
+def test_copy(backend, retry_time):
+ key1 = newname()
+ key2 = newname()
+ value = newvalue()
+ metadata = { 'jimmy': 'jups@42' }
- def tearDown(self):
- self.backend.clear()
- os.rmdir(self.backend_dir)
+ backend.store(key1, value, metadata)
+ # Wait for object to become visible
+ assert_in_index(backend, [key1], retry_time)
+ fetch_object(backend, key1, retry_time)
-class CompressionTestsMixin(BackendTestsMixin):
+ assert_not_in_index(backend, [key2], retry_time)
+ assert_not_readable(backend, key2, retry_time)
- def setUp(self):
- self.name_cnt = 0
- self.backend_dir = tempfile.mkdtemp(prefix='s3ql-backend-')
- self.plain_backend = local.Backend('local://' + self.backend_dir, None, None)
- self.backend = self._wrap_backend()
- self.retries = 0
+ backend.copy(key1, key2)
- def _wrap_backend(self):
- raise RuntimeError("Must be implemented in derived classes.")
+ assert_in_index(backend, [key2], retry_time)
+ (value2, metadata2) = fetch_object(backend, key2, retry_time)
- def tearDown(self):
- self.backend.clear()
- self.backend.close()
- os.rmdir(self.backend_dir)
+ assert value == value2
+ assert metadata == metadata2
- def _make_corrupt_obj(self):
- key = self.newname()
- value = self.newvalue()
+def test_copy_newmeta(backend, retry_time):
+ if isinstance(backend, BetterBackend):
+ pytest.skip('not yet supported for compressed or encrypted backends')
+ key1 = newname()
+ key2 = newname()
+ value = newvalue()
+ meta1 = { 'jimmy': 'jups@42' }
+ meta2 = { 'jiy': 'jfobauske42' }
- self.backend[key] = value
+ backend.store(key1, value, meta1)
- # Corrupt the data
- compr_value = bytearray(self.plain_backend[key])
- compr_value[-3:] = b'000'
- self.plain_backend.store(key, compr_value,
- self.plain_backend.lookup(key))
+ # Wait for object to become visible
+ assert_in_index(backend, [key1], retry_time)
+ fetch_object(backend, key1, retry_time)
- return key
+ assert_not_in_index(backend, [key2], retry_time)
+ assert_not_readable(backend, key2, retry_time)
- def test_corruption(self):
- key = self._make_corrupt_obj()
- with pytest.raises(ChecksumError) as exc:
- self.backend.fetch(key)
- assert exc.value.str == 'Invalid compressed stream'
+ backend.copy(key1, key2, meta2)
- def _make_extended_obj(self):
- key = self.newname()
- value = self.newvalue()
+ assert_in_index(backend, [key2], retry_time)
+ (value2, meta) = fetch_object(backend, key2, retry_time)
- self.backend[key] = value
+ assert value == value2
+ assert meta == meta2
- # Add bogus extra data
- compr_value = self.plain_backend[key]
- compr_value += b'000'
- self.plain_backend.store(key, compr_value,
- self.plain_backend.lookup(key))
+def test_rename(backend, retry_time):
+ key1 = newname()
+ key2 = newname()
+ value = newvalue()
+ metadata = { 'jimmy': 'jups@42' }
- return key
-
- def test_extra_data(self):
- key = self._make_extended_obj()
- with pytest.raises(ChecksumError) as exc:
- self.backend.fetch(key)
- assert exc.value.str == 'Data after end of compressed stream'
+ backend.store(key1, value, metadata)
-
-class ZlibCompressionTests(CompressionTestsMixin, unittest.TestCase):
- def _wrap_backend(self):
- return BetterBackend(None, ('zlib', 6), self.plain_backend)
+ # Wait for object to become visible
+ assert_in_index(backend, [key1], retry_time)
+ fetch_object(backend, key1, retry_time)
-
-class BzipCompressionTests(CompressionTestsMixin, unittest.TestCase):
- def _wrap_backend(self):
- return BetterBackend(None, ('bzip2', 6), self.plain_backend)
+ assert_not_in_index(backend, [key2], retry_time)
+ assert_not_readable(backend, key2, retry_time)
-class LzmaCompressionTests(CompressionTestsMixin, unittest.TestCase):
- def _wrap_backend(self):
- return BetterBackend(None, ('lzma', 6), self.plain_backend)
-
-class EncryptionTests(CompressionTestsMixin, unittest.TestCase):
+ backend.rename(key1, key2)
- def _wrap_backend(self):
- return BetterBackend(b'schluz', (None, 0), self.plain_backend)
+ assert_in_index(backend, [key2], retry_time)
+ (value2, metadata2) = fetch_object(backend, key2, retry_time)
- def test_multi_packet(self):
- with self.backend.open_write('my_obj') as fh:
- for i in range(5):
- fh.write(b'\xFF' * BUFSIZE)
+ assert value == value2
+ assert metadata == metadata2
- with self.backend.open_read('my_obj') as fh:
- while True:
- buf = fh.read(BUFSIZE//2)
- if not buf:
- break
+ assert_not_in_index(backend, [key1], retry_time)
+ assert_not_readable(backend, key1, retry_time)
+
+def test_rename_newmeta(backend, retry_time):
+ if isinstance(backend, BetterBackend):
+ pytest.skip('not yet supported for compressed or encrypted backends')
+ key1 = newname()
+ key2 = newname()
+ value = newvalue()
+ meta1 = { 'jimmy': 'jups@42' }
+ meta2 = { 'apple': 'potatoes' }
- def test_issue431(self):
- hdr_len = struct.calcsize(b'<I')
- with self.backend.open_write('my_obj') as fh:
- fh.write(b'\xFF' * 50)
- fh.write(b'\xFF' * 50)
-
- with self.backend.open_read('my_obj') as fh:
- fh.read(50 + 2*hdr_len)
- fh.read(50)
- assert fh.read(50) == b''
-
- def test_corruption(self):
- key = self._make_corrupt_obj()
- with pytest.raises(ChecksumError) as exc:
- self.backend.fetch(key)
+ backend.store(key1, value, meta1)
+
+ # Wait for object to become visible
+ assert_in_index(backend, [key1], retry_time)
+ fetch_object(backend, key1, retry_time)
+
+ assert_not_in_index(backend, [key2], retry_time)
+ assert_not_readable(backend, key2, retry_time)
+
+ backend.rename(key1, key2, meta2)
+
+ assert_in_index(backend, [key2], retry_time)
+ (value2, meta) = fetch_object(backend, key2, retry_time)
+
+ assert value == value2
+ assert meta == meta2
+
+@require_compression_or_encryption
+def test_corruption(backend, retry_time):
+ plain_backend = backend.backend
+
+ # Create compressed object
+ key = newname()
+ value = newvalue()
+ backend[key] = value
+
+ # Retrieve compressed data
+ (compr_value, meta) = fetch_object(plain_backend, key, retry_time)
+ compr_value = bytearray(compr_value)
+
+ # Create new, corrupt object
+ compr_value[-3:] = b'000'
+ key = newname()
+ plain_backend.store(key, compr_value, meta)
+
+ with pytest.raises(ChecksumError) as exc:
+ fetch_object(backend, key, retry_time)
+
+ if backend.passphrase is None: # compression only
+ assert exc.value.str == 'Invalid compressed stream'
+ else:
assert exc.value.str == 'HMAC mismatch'
- def test_extra_data(self):
- key = self._make_extended_obj()
- with pytest.raises(ChecksumError) as exc:
- self.backend.fetch(key)
+@require_compression_or_encryption
+def test_extra_data(backend, retry_time):
+ plain_backend = backend.backend
+
+ # Create compressed object
+ key = newname()
+ value = newvalue()
+ backend[key] = value
+
+ # Retrieve compressed data
+ (compr_value, meta) = fetch_object(plain_backend, key, retry_time)
+ compr_value = bytearray(compr_value)
+
+ # Create new, corrupt object
+ compr_value += b'000'
+ key = newname()
+ plain_backend.store(key, compr_value, meta)
+
+ with pytest.raises(ChecksumError) as exc:
+ fetch_object(backend, key, retry_time)
+
+ if backend.passphrase is None: # compression only
+ assert exc.value.str == 'Data after end of compressed stream'
+ else:
assert exc.value.str == 'Extraneous data at end of object'
- def test_encryption(self):
-
- self.plain_backend['plain'] = b'foobar452'
- self.backend.store('encrypted', b'testdata', { 'tag': True })
-
- def check1():
- self.assertEqual(self.backend['encrypted'], b'testdata')
- self.assertNotEqual(self.plain_backend['encrypted'], b'testdata')
- self.assertRaises(MalformedObjectError, self.backend.fetch, 'plain')
- self.assertRaises(MalformedObjectError, self.backend.lookup, 'plain')
- self.retry(check1, NoSuchObject)
-
- self.backend.passphrase = None
- self.backend.store('not-encrypted', b'testdata2395', { 'tag': False })
- def check2():
- self.assertRaises(ChecksumError, self.backend.fetch, 'encrypted')
- self.assertRaises(ChecksumError, self.backend.lookup, 'encrypted')
- self.retry(check2, NoSuchObject)
-
-
- self.backend.passphrase = b'jobzrul'
- def check3():
- self.assertRaises(ChecksumError, self.backend.fetch, 'encrypted')
- self.assertRaises(ChecksumError, self.backend.lookup, 'encrypted')
- self.assertRaises(ObjectNotEncrypted, self.backend.fetch, 'not-encrypted')
- self.assertRaises(ObjectNotEncrypted, self.backend.lookup, 'not-encrypted')
- self.retry(check3, NoSuchObject)
-
-
-class EncryptionCompressionTests(EncryptionTests):
-
- def _wrap_backend(self):
- return BetterBackend(b'schlurz', ('zlib', 6), self.plain_backend)
-
-
-class URLTests(unittest.TestCase):
-
- # access to protected members
- #pylint: disable=W0212
-
- def test_s3(self):
- self.assertEqual(s3.Backend._parse_storage_url('s3://name', ssl_context=None)[2:],
- ('name', ''))
- self.assertEqual(s3.Backend._parse_storage_url('s3://name/', ssl_context=None)[2:],
- ('name', ''))
- self.assertEqual(s3.Backend._parse_storage_url('s3://name/pref/', ssl_context=None)[2:],
- ('name', 'pref/'))
- self.assertEqual(s3.Backend._parse_storage_url('s3://name//pref/', ssl_context=None)[2:],
- ('name', '/pref/'))
-
- def test_gs(self):
- self.assertEqual(gs.Backend._parse_storage_url('gs://name', ssl_context=None)[2:],
- ('name', ''))
- self.assertEqual(gs.Backend._parse_storage_url('gs://name/', ssl_context=None)[2:],
- ('name', ''))
- self.assertEqual(gs.Backend._parse_storage_url('gs://name/pref/', ssl_context=None)[2:],
- ('name', 'pref/'))
- self.assertEqual(gs.Backend._parse_storage_url('gs://name//pref/', ssl_context=None)[2:],
- ('name', '/pref/'))
-
- def test_s3c(self):
- self.assertEqual(s3c.Backend._parse_storage_url('s3c://host.org/name', ssl_context=None),
- ('host.org', 80, 'name', ''))
- self.assertEqual(s3c.Backend._parse_storage_url('s3c://host.org:23/name', ssl_context=None),
- ('host.org', 23, 'name', ''))
- self.assertEqual(s3c.Backend._parse_storage_url('s3c://host.org/name/', ssl_context=None),
- ('host.org', 80, 'name', ''))
- self.assertEqual(s3c.Backend._parse_storage_url('s3c://host.org/name/pref', ssl_context=None),
- ('host.org', 80, 'name', 'pref'))
- self.assertEqual(s3c.Backend._parse_storage_url('s3c://host.org:17/name/pref/', ssl_context=None),
- ('host.org', 17, 'name', 'pref/'))
+def test_multi_packet(backend):
+ '''Write and read packet extending over multiple chunks'''
+ key = newname()
+
+ def do_write(fh):
+ for i in range(5):
+ fh.write(b'\xFF' * BUFSIZE)
+ backend.perform_write(do_write, key)
+
+ def do_read(fh):
+ buf = bytearray()
+ while True:
+ tmp = fh.read(BUFSIZE//2)
+ if not tmp:
+ break
+ buf += tmp
+ return buf
+ res = backend.perform_read(do_read, key)
+ assert res == b'\xFF' * (5*BUFSIZE)
+
+# No short reads
+@require_plain_backend(LocalBackend)
+@require_compression_or_encryption
+def test_issue431(backend):
+ key = newname()
+ hdr_len = struct.calcsize(b'<I')
+
+ def do_write(fh):
+ fh.write(b'\xFF' * 50)
+ fh.write(b'\xFF' * 50)
+ backend.perform_write(do_write, key)
+
+ def do_read(fh):
+ fh.read(50 + 2*hdr_len)
+ fh.read(50)
+ assert fh.read(50) == b''
+ backend.perform_read(do_read, key)
+
+@require_immediate_consistency
+@require_encryption
+def test_encryption(backend):
+ plain_backend = backend.backend
+
+ plain_backend['plain'] = b'foobar452'
+ backend.store('encrypted', b'testdata', { 'tag': True })
+
+ assert plain_backend['encrypted'] != b'testdata'
+ assert_raises(MalformedObjectError, backend.fetch, 'plain')
+ assert_raises(MalformedObjectError, backend.lookup, 'plain')
+
+ backend.passphrase = None
+ backend.store('not-encrypted', b'testdata2395', { 'tag': False })
+ assert_raises(ChecksumError, backend.fetch, 'encrypted')
+ assert_raises(ChecksumError, backend.lookup, 'encrypted')
+
+ backend.passphrase = b'jobzrul'
+ assert_raises(ChecksumError, backend.fetch, 'encrypted')
+ assert_raises(ChecksumError, backend.lookup, 'encrypted')
+ assert_raises(ObjectNotEncrypted, backend.fetch, 'not-encrypted')
+ assert_raises(ObjectNotEncrypted, backend.lookup, 'not-encrypted')
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_corrupted_get(backend, backend_wrapper, monkeypatch):
+ key = 'brafasel'
+ value = b'hello there, let us see whats going on'
+ backend[key] = value
+
+ # Monkeypatch request handler to produce invalid etag
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def send_header(self, keyword ,value, count=[0],
+ send_header_real=handler_class.send_header):
+ if keyword == 'ETag':
+ count[0] += 1
+ if count[0] <= 3:
+ value = value[::-1]
+ return send_header_real(self, keyword, value)
+ monkeypatch.setattr(handler_class, 'send_header', send_header)
+
+ with catch_logmsg('^MD5 mismatch for', count=1, level=logging.WARNING):
+ assert_raises(BadDigestError, backend.fetch, key)
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ with catch_logmsg('^MD5 mismatch for', count=2, level=logging.WARNING):
+ assert backend[key] == value
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_corrupted_put(backend, backend_wrapper, monkeypatch):
+ key = 'brafasel'
+ value = b'hello there, let us see whats going on'
+
+ # Monkeypatch request handler to produce invalid etag
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def send_header(self, keyword ,value, count=[0],
+ send_header_real=handler_class.send_header):
+ if keyword == 'ETag':
+ count[0] += 1
+ if count[0] < 3:
+ value = value[::-1]
+ return send_header_real(self, keyword, value)
+ monkeypatch.setattr(handler_class, 'send_header', send_header)
+
+ fh = backend.open_write(key)
+ fh.write(value)
+ assert_raises(BadDigestError, fh.close)
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ fh.close()
+
+ assert backend[key] == value
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_get_s3error(backend, backend_wrapper, monkeypatch):
+ value = b'hello there, let us see whats going on'
+ key = 'quote'
+ backend[key] = value
+
+ # Monkeypatch request handler to produce 3 errors
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def do_GET(self, real_GET=handler_class.do_GET, count=[0]):
+ count[0] += 1
+ if count[0] > 3:
+ return real_GET(self)
+ else:
+ self.send_error(503, code='OperationAborted')
+ monkeypatch.setattr(handler_class, 'do_GET', do_GET)
+ assert_raises(OperationAbortedError, backend.fetch, value)
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ assert backend[key] == value
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_head_s3error(backend, backend_wrapper, monkeypatch):
+ value = b'hello there, let us see whats going on'
+ key = 'quote'
+ meta = {'bar': 42, 'foo': 42**2}
+ backend.store(key, value, metadata=meta)
+
+ # Monkeypatch request handler to produce 3 errors
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def do_HEAD(self, real_HEAD=handler_class.do_HEAD, count=[0]):
+ count[0] += 1
+ if count[0] > 3:
+ return real_HEAD(self)
+ else:
+ self.send_error(503, code='OperationAborted')
+ monkeypatch.setattr(handler_class, 'do_HEAD', do_HEAD)
+ with pytest.raises(HTTPError) as exc:
+ backend.lookup(key)
+ assert exc.value.status == 503
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ assert backend.lookup(key) == meta
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_delete_s3error(backend, backend_wrapper, monkeypatch):
+ value = b'hello there, let us see whats going on'
+ key = 'quote'
+ backend[key] = value
+
+ # Monkeypatch request handler to produce 3 errors
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def do_DELETE(self, real_DELETE=handler_class.do_DELETE, count=[0]):
+ count[0] += 1
+ if count[0] > 3:
+ return real_DELETE(self)
+ else:
+ self.send_error(503, code='OperationAborted')
+ monkeypatch.setattr(handler_class, 'do_DELETE', do_DELETE)
+ assert_raises(OperationAbortedError, backend.delete, key)
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ backend.delete(key)
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_backoff(backend, backend_wrapper, monkeypatch):
+ value = b'hello there, let us see whats going on'
+ key = 'quote'
+ backend[key] = value
+
+ # Monkeypatch request handler
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ timestamps = []
+ def do_DELETE(self, real_DELETE=handler_class.do_DELETE):
+ timestamps.append(time.time())
+ if len(timestamps) < 3:
+ self.send_error(503, code='SlowDown',
+ extra_headers={'Retry-After': '1'})
+ else:
+ return real_DELETE(self)
+
+ monkeypatch.setattr(handler_class, 'do_DELETE', do_DELETE)
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ backend.delete(key)
+
+ assert timestamps[1] - timestamps[0] > 1
+ assert timestamps[2] - timestamps[1] > 1
+ assert timestamps[2] - timestamps[0] < 10
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_httperror(backend, backend_wrapper, monkeypatch):
+ value = b'hello there, let us see whats going on'
+ key = 'quote'
+ backend[key] = value
+
+ # Monkeypatch request handler to produce a HTTP Error
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def do_DELETE(self, real_DELETE=handler_class.do_DELETE, count=[0]):
+ count[0] += 1
+ if count[0] >= 3:
+ return real_DELETE(self)
+ content = "I'm a proxy, and I messed up!".encode('utf-8')
+ self.send_response(502, "Bad Gateway")
+ self.send_header("Content-Type", 'text/plain; charset="utf-8"')
+ self.send_header("Content-Length", str(len(content)))
+ self.end_headers()
+ if self.command != 'HEAD':
+ self.wfile.write(content)
+
+ monkeypatch.setattr(handler_class, 'do_DELETE', do_DELETE)
+ assert_raises(HTTPError, backend.delete, key)
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ backend.delete(key)
+
+# Require mock backend and expect-100 support
+@require_wrapper(lambda x: isinstance(x, MockBackendWrapper)
+ and x.backend.use_expect_100c)
+def test_put_s3error_early(backend, backend_wrapper, monkeypatch):
+ '''Fail after expect-100'''
+
+ data = b'hello there, let us see whats going on'
+ key = 'borg'
+
+ # Monkeypatch request handler to produce 3 errors
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def handle_expect_100(self, real=handler_class.handle_expect_100, count=[0]):
+ count[0] += 1
+ if count[0] > 3:
+ return real(self)
+ else:
+ self.send_error(503, code='OperationAborted')
+ return False
+ monkeypatch.setattr(handler_class, 'handle_expect_100', handle_expect_100)
+ fh = backend.open_write(key)
+ fh.write(data)
+ assert_raises(OperationAbortedError, fh.close)
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ fh.close()
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_put_s3error_med(backend, backend_wrapper, monkeypatch):
+ '''Fail as soon as data is received'''
+ data = b'hello there, let us see whats going on'
+ key = 'borg'
+
+ # Monkeypatch request handler to produce 3 errors
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def do_PUT(self, real_PUT=handler_class.do_PUT, count=[0]):
+ count[0] += 1
+ # Note: every time we return an error, the request will be retried
+ # *twice*: once because of the error, and a second time because the
+ # connection has been closed by the server.
+ if count[0] > 2:
+ return real_PUT(self)
+ else:
+ self.send_error(503, code='OperationAborted')
+
+ # Since we don't read all the data, we have to close
+ # the connection
+ self.close_connection = True
+
+ monkeypatch.setattr(handler_class, 'do_PUT', do_PUT)
+ fh = backend.open_write(key)
+ fh.write(data)
+ assert_raises(OperationAbortedError, fh.close)
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ fh.close()
+
+@require_backend_wrapper(MockBackendWrapper)
+def test_put_s3error_late(backend, backend_wrapper, monkeypatch):
+ '''Fail after reading all data'''
+ data = b'hello there, let us see whats going on'
+ key = 'borg'
+
+ # Monkeypatch request handler to produce 3 errors
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def do_PUT(self, real_PUT=handler_class.do_PUT, count=[0]):
+ count[0] += 1
+ if count[0] > 3:
+ return real_PUT(self)
+ else:
+ self.rfile.read(int(self.headers['Content-Length']))
+ self.send_error(503, code='OperationAborted')
+
+ monkeypatch.setattr(handler_class, 'do_PUT', do_PUT)
+ fh = backend.open_write(key)
+ fh.write(data)
+ assert_raises(OperationAbortedError, fh.close)
+
+ monkeypatch.setattr(backend_wrapper, 'may_temp_fail', True)
+ fh.close()
+
+# Require mock server *and* google storage backend
+@require_wrapper(lambda x: isinstance(x, MockBackendWrapper)
+ and isinstance(x.backend, GSBackend))
+def test_expired_token(backend, backend_wrapper, monkeypatch):
+ '''Test handling of expired OAuth token'''
+
+
+ key = 'borg'
+ data = b'hello there, let us see whats going on'
+
+ # Monkeypatch backend class to check if token is refreshed
+ token_refreshed = False
+ def _get_access_token(self):
+ nonlocal token_refreshed
+ token_refreshed = True
+ self.access_token[self.password] = 'foobar'
+ monkeypatch.setattr(GSBackend, '_get_access_token',
+ _get_access_token)
+
+ # Store some data
+ backend[key] = data
+
+ # Monkeypatch request handler to produce error
+ handler_class = backend_wrapper.server.RequestHandlerClass
+ def do_GET(self, real=handler_class.do_GET, count=[0]):
+ count[0] += 1
+ if count[0] > 1:
+ return real(self)
+ else:
+ self.send_error(401, code='AuthenticationRequired')
+ monkeypatch.setattr(handler_class, 'do_GET', do_GET)
+
+ token_refreshed = False
+ assert backend[key] == data
+ assert token_refreshed
+
+def test_s3_url_parsing():
+ parse = backends.s3.Backend._parse_storage_url
+ assert parse('s3://name', ssl_context=None)[2:] == ('name', '')
+ assert parse('s3://name/', ssl_context=None)[2:] == ('name', '')
+ assert parse('s3://name/pref/', ssl_context=None)[2:] == ('name', 'pref/')
+ assert parse('s3://name//pref/', ssl_context=None)[2:] == ('name', '/pref/')
+
+def test_gs_url_parsing():
+ parse = backends.gs.Backend._parse_storage_url
+ assert parse('gs://name', ssl_context=None)[2:] == ('name', '')
+ assert parse('gs://name/', ssl_context=None)[2:] == ('name', '')
+ assert parse('gs://name/pref/', ssl_context=None)[2:] == ('name', 'pref/')
+ assert parse('gs://name//pref/', ssl_context=None)[2:] == ('name', '/pref/')
+
+def test_s3c_url_parsing():
+ parse = backends.s3c.Backend._parse_storage_url
+ assert parse('s3c://host.org/name', ssl_context=None) == ('host.org', 80, 'name', '')
+ assert parse('s3c://host.org:23/name', ssl_context=None) == ('host.org', 23, 'name', '')
+ assert parse('s3c://host.org/name/', ssl_context=None) == ('host.org', 80, 'name', '')
+ assert parse('s3c://host.org/name/pref',
+ ssl_context=None) == ('host.org', 80, 'name', 'pref')
+ assert parse('s3c://host.org:17/name/pref/',
+ ssl_context=None) == ('host.org', 17, 'name', 'pref/')
diff --git a/tests/t1_dump.py b/tests/t1_dump.py
index 6ac38d9..74d8438 100755
--- a/tests/t1_dump.py
+++ b/tests/t1_dump.py
@@ -30,7 +30,7 @@ class DumpTests(unittest.TestCase):
# Disable exclusive locking for all tests
self.src.execute('PRAGMA locking_mode = NORMAL')
self.dst.execute('PRAGMA locking_mode = NORMAL')
-
+
self.create_table(self.src)
self.create_table(self.dst)
@@ -43,7 +43,7 @@ class DumpTests(unittest.TestCase):
def test_transactions(self):
self.fill_vals(self.src)
- dumpspec = (('id', deltadump.INTEGER, 0),)
+ dumpspec = (('id', deltadump.INTEGER, 0),)
deltadump.dump_table(table='test', order='id', columns=dumpspec,
db=self.src, fh=self.fh)
self.fh.seek(0)
@@ -52,7 +52,7 @@ class DumpTests(unittest.TestCase):
deltadump.load_table(table='test', columns=dumpspec, db=self.dst,
fh=self.fh, trx_rows=10)
self.compare_tables(self.src, self.dst)
-
+
def test_1_vals_1(self):
self.fill_vals(self.src)
dumpspec = (('id', deltadump.INTEGER, 0),)
@@ -201,7 +201,7 @@ class DumpTests(unittest.TestCase):
val = rfh.read(random.randint(0, 140))
else:
val = rfh.read(len_)
-
+
db.execute('UPDATE test SET buf=? WHERE id=?', (val, id_))
def fill_vals(self, db):
diff --git a/tests/t1_retry.py b/tests/t1_retry.py
index f9c0de0..1c014d1 100755
--- a/tests/t1_retry.py
+++ b/tests/t1_retry.py
@@ -34,7 +34,7 @@ class NthAttempt:
return True
self.count += 1
raise TemporaryProblem()
-
+
@retry_generator
def list_stuff(self, upto=10, start_after=-1):
for i in range(upto):
@@ -47,12 +47,12 @@ class NthAttempt:
if i == 7 and self.count < 4:
self.count += 1
raise TemporaryProblem
-
+
yield i
-
+
def test_retry():
inst = NthAttempt(3)
-
+
assert inst.do_stuff()
def test_retry_generator():
@@ -61,7 +61,6 @@ def test_retry_generator():
def test_logging():
inst = NthAttempt(6)
- with catch_logmsg('^Encountered %s exception',
+ with catch_logmsg('^Encountered %s exception',
count=2, level=logging.WARNING):
inst.do_stuff()
-
diff --git a/tests/t2_block_cache.py b/tests/t2_block_cache.py
index 408136a..b7d55b5 100755
--- a/tests/t2_block_cache.py
+++ b/tests/t2_block_cache.py
@@ -42,7 +42,7 @@ class DummyQueue:
def get_nowait(self):
return self.get(block=False)
-
+
def put(self, obj, timeout=None):
self.obj = obj
self.cache._removal_loop()
@@ -64,15 +64,15 @@ class cache_tests(unittest.TestCase):
def setUp(self):
self.backend_dir = tempfile.mkdtemp(prefix='s3ql-backend-')
- self.backend_pool = BackendPool(lambda: local.Backend('local://' + self.backend_dir,
+ self.backend_pool = BackendPool(lambda: local.Backend('local://' + self.backend_dir,
None, None))
self.cachedir = tempfile.mkdtemp(prefix='s3ql-cache-')
self.max_obj_size = 1024
# Destructors are not guaranteed to run, and we can't unlink
- # the file immediately because apsw refers to it by name.
- # Therefore, we unlink the file manually in tearDown()
+ # the file immediately because apsw refers to it by name.
+ # Therefore, we unlink the file manually in tearDown()
self.dbfile = tempfile.NamedTemporaryFile(delete=False)
self.db = Connection(self.dbfile.name)
create_tables(self.db)
@@ -89,7 +89,7 @@ class cache_tests(unittest.TestCase):
cache = BlockCache(self.backend_pool, self.db, self.cachedir + "/cache",
self.max_obj_size * 100)
self.cache = cache
-
+
# Monkeypatch around the need for removal and upload threads
cache.to_remove = DummyQueue(cache)
@@ -98,7 +98,7 @@ class cache_tests(unittest.TestCase):
cache._do_upload(*arg)
return True
cache.to_upload = DummyDistributor()
-
+
# Tested methods assume that they are called from
# file system request handler
llfuse.lock.acquire()
@@ -115,26 +115,20 @@ class cache_tests(unittest.TestCase):
# Make sure that we don't deadlock if some upload threads
# terminate prematurely
- # Create an object
- with self.cache.get(self.inode, 0) as fh:
- fh.seek(0)
- fh.write(b'barf!')
- self.cache.commit()
-
- # Monkeypatch to avoid error messages about uncaught exceptinons
+ # Monkeypatch to avoid error messages about uncaught exceptions
# in other threads
upload_exc = False
removal_exc = False
def _upload_loop(*a, fn=self.cache._upload_loop):
try:
return fn(*a)
- except PermissionError:
+ except NotADirectoryError:
nonlocal upload_exc
upload_exc = True
def _removal_loop(*a, fn=self.cache._removal_loop):
try:
return fn(*a)
- except (PermissionError, NoSuchObject):
+ except (NotADirectoryError, NoSuchObject):
nonlocal removal_exc
removal_exc = True
self.cache._upload_loop = _upload_loop
@@ -144,13 +138,14 @@ class cache_tests(unittest.TestCase):
self.cache.init(threads=5)
# Make sure that upload and removal will fail
- os.chmod(self.backend_dir + '/s3ql_data_', 0o555)
-
+ os.rename(self.backend_dir, self.backend_dir + '-tmp')
+ open(self.backend_dir, 'w').close()
+
# Create another object
with self.cache.get(self.inode, 1) as fh:
fh.seek(0)
fh.write(b'bar wurfz!')
-
+
# Remove something
self.cache.remove(self.inode, 0)
@@ -163,14 +158,21 @@ class cache_tests(unittest.TestCase):
self.cache.destroy()
assert exc_info.value.errno == errno.ENOTEMPTY
finally:
- # Fix permissions and make second destroy call into no-op
- os.chmod(self.backend_dir + '/s3ql_data_', 0o755)
+ # Fix backend dir and make second destroy call into no-op
+ os.unlink(self.backend_dir)
+ os.rename(self.backend_dir + '-tmp', self.backend_dir)
self.cache.destroy = lambda: None
+
+ # Remove elements from cache, or we get a warning from
+ # BlockCache.__del__
+ for key in self.cache.cache.keys():
+ self.cache.cache.remove(key)
+
llfuse.lock.acquire()
assert removal_exc
assert upload_exc
-
+
def test_expire_deadlock(self):
# Make sure that we don't deadlock if uploads threads
# are gone and we try to expire
@@ -181,7 +183,7 @@ class cache_tests(unittest.TestCase):
def _upload_loop(*a, fn=self.cache._upload_loop):
try:
return fn(*a)
- except PermissionError:
+ except NotADirectoryError:
nonlocal upload_exc
upload_exc = True
self.cache._upload_loop = _upload_loop
@@ -191,7 +193,7 @@ class cache_tests(unittest.TestCase):
def _removal_loop(*a, fn=self.cache._removal_loop):
try:
return fn(*a)
- except NoSuchObject:
+ except (NoSuchObject, NotADirectoryError):
pass
self.cache._removal_loop = _removal_loop
@@ -199,8 +201,9 @@ class cache_tests(unittest.TestCase):
self.cache.init(threads=3)
# Make sure that upload will fail
- os.chmod(self.backend_dir, 0o555)
-
+ os.rename(self.backend_dir, self.backend_dir + '-tmp')
+ open(self.backend_dir, 'w').close()
+
# Create object
with self.cache.get(self.inode, 0) as fh:
fh.write(b'bar wurfz!')
@@ -209,12 +212,13 @@ class cache_tests(unittest.TestCase):
with pytest.raises(NoWorkerThreads):
self.cache.clear()
- # Fix permissions, remove object
- os.chmod(self.backend_dir, 0o755)
+ # Fix backend dir and remove object
+ os.unlink(self.backend_dir)
+ os.rename(self.backend_dir + '-tmp', self.backend_dir)
self.cache.remove(self.inode, 0)
assert upload_exc
-
+
@staticmethod
def random_data(len_):
with open("/dev/urandom", "rb") as fh:
@@ -390,10 +394,10 @@ class cache_tests(unittest.TestCase):
# Remove it
self.cache.remove(inode, blockno)
-
+
# Try to upload it, may happen if CommitThread is interrupted
self.cache.upload(fh)
-
+
def test_expire_race(self):
# Create element
inode = self.inode
@@ -409,31 +413,31 @@ class cache_tests(unittest.TestCase):
def e_w_l():
with llfuse.lock:
self.cache.expire()
-
+
# Lock it
self.cache._lock_entry(inode, blockno, release_global=True)
- try:
+ try:
# Start expiration, will block on lock
t1 = AsyncFn(e_w_l)
t1.start()
-
+
# Start second expiration, will block
t2 = AsyncFn(e_w_l)
t2.start()
-
+
# Release lock
with llfuse.lock_released:
time.sleep(0.1)
self.cache._unlock_entry(inode, blockno)
t1.join_and_raise()
t2.join_and_raise()
-
+
assert len(self.cache.cache) == 0
finally:
self.cache._unlock_entry(inode, blockno, release_global=True,
noerror=True)
-
+
def test_parallel_expire(self):
# Create elements
@@ -449,37 +453,37 @@ class cache_tests(unittest.TestCase):
def e_w_l():
with llfuse.lock:
self.cache.expire()
-
+
# Lock first element so that we have time to start threads
self.cache._lock_entry(inode, 0, release_global=True)
- try:
+ try:
# Start expiration, will block on lock
t1 = AsyncFn(e_w_l)
t1.start()
-
+
# Start second expiration, will block
t2 = AsyncFn(e_w_l)
t2.start()
-
+
# Release lock
with llfuse.lock_released:
time.sleep(0.1)
self.cache._unlock_entry(inode, 0)
t1.join_and_raise()
t2.join_and_raise()
-
+
assert len(self.cache.cache) == 4
finally:
self.cache._unlock_entry(inode, 0, release_global=True,
noerror=True)
-
-
+
+
def test_remove_cache_db(self):
inode = self.inode
data1 = self.random_data(int(0.4 * self.max_obj_size))
- # Case 2: Element in cache and db
+ # Case 2: Element in cache and db
with self.cache.get(inode, 1) as fh:
fh.seek(0)
fh.write(data1)
@@ -513,7 +517,7 @@ class cache_tests(unittest.TestCase):
fh.seek(0)
self.assertEqual(fh.read(42), b'')
-
+
class TestBackendPool(AbstractBackend):
def __init__(self, backend_pool, no_read=0, no_write=0, no_del=0):
super().__init__()
@@ -584,15 +588,15 @@ class TestBackendPool(AbstractBackend):
def copy(self, src, dest):
"""Copy data stored under key `src` to key `dest`
-
+
If `dest` already exists, it will be overwritten. The copying
- is done on the remote side.
+ is done on the remote side.
"""
return self.backend.copy(src, dest)
def rename(self, src, dest):
"""Rename key `src` to `dest`
-
+
If `dest` already exists, it will be overwritten. The rename
is done on the remote side.
"""
@@ -605,7 +609,7 @@ class TestBackendPool(AbstractBackend):
def commit(cache, inode, block=None):
"""Upload data for `inode`
-
+
This is only for testing purposes, since the method blocks until all current
uploads have been completed.
"""
@@ -620,4 +624,3 @@ def commit(cache, inode, block=None):
continue
cache.upload(el)
-
diff --git a/tests/t3_fs_api.py b/tests/t3_fs_api.py
index 3c376f6..81c912e 100755
--- a/tests/t3_fs_api.py
+++ b/tests/t3_fs_api.py
@@ -65,10 +65,10 @@ class fs_api_tests(unittest.TestCase):
self.max_obj_size = 1024
# Destructors are not guaranteed to run, and we can't unlink
- # the file immediately because apsw refers to it by name.
- # Therefore, we unlink the file manually in tearDown()
+ # the file immediately because apsw refers to it by name.
+ # Therefore, we unlink the file manually in tearDown()
self.dbfile = tempfile.NamedTemporaryFile(delete=False)
-
+
self.db = Connection(self.dbfile.name)
create_tables(self.db)
init_tables(self.db)
@@ -92,7 +92,7 @@ class fs_api_tests(unittest.TestCase):
cache._do_upload(*arg)
return True
cache.to_upload = DummyDistributor()
-
+
# Keep track of unused filenames
self.name_cnt = 0
@@ -670,10 +670,10 @@ class fs_api_tests(unittest.TestCase):
self.server.write(fh, 0, data)
self.server.cache.clear()
self.assertTrue(self.server.failsafe is False)
-
+
datafile = os.path.join(self.backend_dir, 's3ql_data_', 's3ql_data_1')
shutil.copy(datafile, datafile + '.bak')
-
+
# Modify contents
with open(datafile, 'rb+') as rfh:
rfh.seek(560)
@@ -690,20 +690,20 @@ class fs_api_tests(unittest.TestCase):
with self.assertRaises(FUSEError) as cm:
self.server.read(fh, 0, len_)
self.assertEqual(cm.exception.errno, errno.EIO)
-
+
# Release and re-open, now we should be able to access again
self.server.release(fh)
self.server.forget([(inode.id, 1)])
-
+
# ..but not write access since we are in failsafe mode
with self.assertRaises(FUSEError) as cm:
self.server.open(inode.id, os.O_RDWR)
self.assertEqual(cm.exception.errno, errno.EPERM)
-
+
# ..ready only is fine.
fh = self.server.open(inode.id, os.O_RDONLY)
self.server.read(fh, 0, len_)
-
+
# Remove completely, should give error after cache flush
os.unlink(datafile)
self.server.read(fh, 3, len_//2)
@@ -713,10 +713,10 @@ class fs_api_tests(unittest.TestCase):
count=1, level=logging.ERROR):
self.server.read(fh, 5, len_//2)
self.assertEqual(cm.exception.errno, errno.EIO)
-
-
+
+
# Don't call fsck, we're missing a block
-
+
def test_create_open(self):
name = self.newname()
# Create a new file
diff --git a/tests/t3_fsck.py b/tests/t3_fsck.py
index c562e35..058df60 100755
--- a/tests/t3_fsck.py
+++ b/tests/t3_fsck.py
@@ -186,7 +186,7 @@ class fsck_tests(unittest.TestCase):
def _add_name(self, name):
'''Get id for *name* and increase refcount
-
+
Name is inserted in table if it does not yet exist.
'''
@@ -341,7 +341,7 @@ class fsck_tests(unittest.TestCase):
def test_loops(self):
- # Create some directory inodes
+ # Create some directory inodes
inodes = [ self.db.rowid("INSERT INTO inodes (mode,uid,gid,mtime,atime,ctime,refcount) "
"VALUES (?,?,?,?,?,?,?)",
(stat.S_IFDIR | stat.S_IRUSR | stat.S_IWUSR,
@@ -477,7 +477,7 @@ class fsck_tests(unittest.TestCase):
self._link(b'test-entry', inode)
self.assert_fsck(self.fsck.check_unix)
-
+
newmode = self.db.get_val('SELECT mode FROM inodes WHERE id=?', (inode,))
self.assertEqual(stat.S_IMODE(newmode), perms)
self.assertEqual(stat.S_IFMT(newmode), stat.S_IFREG)
@@ -491,19 +491,19 @@ class fsck_tests(unittest.TestCase):
(perms, os.getuid(), os.getgid(), stamp, stamp, stamp, 1))
inode2 = self.db.rowid("INSERT INTO inodes (mode,uid,gid,mtime,atime,ctime,refcount) "
"VALUES (?,?,?,?,?,?,?)",
- (perms | stat.S_IFREG, os.getuid(), os.getgid(), stamp,
+ (perms | stat.S_IFREG, os.getuid(), os.getgid(), stamp,
stamp, stamp, 1))
self._link(b'test-entry', inode)
self._link(b'subentry', inode2, inode)
self.assert_fsck(self.fsck.check_unix)
-
+
newmode = self.db.get_val('SELECT mode FROM inodes WHERE id=?', (inode,))
self.assertEqual(stat.S_IMODE(newmode), perms)
self.assertEqual(stat.S_IFMT(newmode), stat.S_IFDIR)
-
-
+
+
def test_unix_symlink_no_target(self):
inode = self.db.rowid("INSERT INTO inodes (mode,uid,gid,mtime,atime,ctime,refcount) "
diff --git a/tests/t3_inode_cache.py b/tests/t3_inode_cache.py
index a117afa..5b0125d 100755
--- a/tests/t3_inode_cache.py
+++ b/tests/t3_inode_cache.py
@@ -25,10 +25,10 @@ class cache_tests(unittest.TestCase):
def setUp(self):
# Destructors are not guaranteed to run, and we can't unlink
- # the file immediately because apsw refers to it by name.
- # Therefore, we unlink the file manually in tearDown()
+ # the file immediately because apsw refers to it by name.
+ # Therefore, we unlink the file manually in tearDown()
self.dbfile = tempfile.NamedTemporaryFile(delete=False)
-
+
self.db = Connection(self.dbfile.name)
create_tables(self.db)
init_tables(self.db)
diff --git a/tests/t4_adm.py b/tests/t4_adm.py
index 18d13f8..094f9e3 100755
--- a/tests/t4_adm.py
+++ b/tests/t4_adm.py
@@ -36,7 +36,7 @@ class AdmTests(unittest.TestCase):
shutil.rmtree(self.backend_dir)
def mkfs(self):
- proc = subprocess.Popen(self.s3ql_cmd_argv('mkfs.s3ql') +
+ proc = subprocess.Popen(self.s3ql_cmd_argv('mkfs.s3ql') +
['-L', 'test fs', '--max-obj-size', '500', '--fatal-warnings',
'--authfile', '/dev/null', '--cachedir', self.cache_dir,
'--quiet', self.storage_url ],
@@ -53,7 +53,7 @@ class AdmTests(unittest.TestCase):
passphrase_new = 'sd982jhd'
- proc = subprocess.Popen(self.s3ql_cmd_argv('s3qladm') +
+ proc = subprocess.Popen(self.s3ql_cmd_argv('s3qladm') +
[ '--quiet', '--fatal-warnings', '--log', 'none', '--authfile',
'/dev/null', 'passphrase', self.storage_url ],
stdin=subprocess.PIPE, universal_newlines=True)
@@ -67,8 +67,8 @@ class AdmTests(unittest.TestCase):
plain_backend = local.Backend(self.storage_url, None, None)
backend = BetterBackend(passphrase_new.encode(), ('zlib', 6), plain_backend)
-
- backend.fetch('s3ql_passphrase') # will fail with wrong pw
+
+ backend.fetch('s3ql_passphrase') # will fail with wrong pw
def test_authinfo(self):
@@ -85,7 +85,7 @@ class AdmTests(unittest.TestCase):
file=fh, sep='\n')
fh.flush()
- proc = subprocess.Popen(self.s3ql_cmd_argv('fsck.s3ql') +
+ proc = subprocess.Popen(self.s3ql_cmd_argv('fsck.s3ql') +
[ '--quiet', '--fatal-warnings', '--authfile', fh.name,
'--cachedir', self.cache_dir, '--log', 'none', self.storage_url ],
stdin=subprocess.PIPE, universal_newlines=True)
diff --git a/tests/t4_fuse.py b/tests/t4_fuse.py
index 33869ac..5ec355f 100755
--- a/tests/t4_fuse.py
+++ b/tests/t4_fuse.py
@@ -56,7 +56,7 @@ class fuse_tests(unittest.TestCase):
self.name_cnt = 0
def mkfs(self, max_obj_size=500):
- proc = subprocess.Popen(self.s3ql_cmd_argv('mkfs.s3ql') +
+ proc = subprocess.Popen(self.s3ql_cmd_argv('mkfs.s3ql') +
[ '-L', 'test fs', '--max-obj-size', str(max_obj_size),
'--fatal-warnings', '--cachedir', self.cache_dir, '--quiet',
'--authfile', '/dev/null', self.storage_url ],
@@ -121,7 +121,7 @@ class fuse_tests(unittest.TestCase):
file=authinfo_fh, sep='\n')
authinfo_fh.flush()
- proc = subprocess.Popen(self.s3ql_cmd_argv('fsck.s3ql') +
+ proc = subprocess.Popen(self.s3ql_cmd_argv('fsck.s3ql') +
[ '--force', '--quiet', '--log', 'none', '--cachedir',
self.cache_dir, '--fatal-warnings', '--authfile',
authinfo_fh.name, self.storage_url ],
@@ -151,9 +151,9 @@ class fuse_tests(unittest.TestCase):
def test_all(self):
- # Workaround py.test not calling runTest
+ # Workaround py.test not calling runTest
return self.runTest()
-
+
def runTest(self):
# Run all tests in same environment, mounting and umounting
# just takes too long otherwise
@@ -323,7 +323,7 @@ class fuse_tests(unittest.TestCase):
fstat = os.stat(filename)
size = fstat.st_size
- subprocess.check_call(self.s3ql_cmd_argv('s3qlctrl') +
+ subprocess.check_call(self.s3ql_cmd_argv('s3qlctrl') +
[ '--quiet', 'flushcache', self.mnt_dir ])
fd = os.open(filename, os.O_RDWR)
@@ -343,10 +343,8 @@ class fuse_tests(unittest.TestCase):
os.mkdir(fullname)
self.assertTrue(stat.S_ISDIR(os.stat(fullname).st_mode))
self.assertTrue(dirname in llfuse.listdir(self.mnt_dir))
- llfuse.setxattr('%s/%s' % (self.mnt_dir, CTRL_NAME),
+ llfuse.setxattr('%s/%s' % (self.mnt_dir, CTRL_NAME),
'rmtree', pickle.dumps((llfuse.ROOT_INODE, path2bytes(dirname)),
PICKLE_PROTOCOL))
self.assertRaises(FileNotFoundError, os.stat, fullname)
self.assertTrue(dirname not in llfuse.listdir(self.mnt_dir))
-
-
diff --git a/tests/t5_cp.py b/tests/t5_cp.py
index 3565160..3457c58 100755
--- a/tests/t5_cp.py
+++ b/tests/t5_cp.py
@@ -44,7 +44,7 @@ class cpTests(t4_fuse.fuse_tests):
os.path.join(self.mnt_dir, 'orig') + '/'])
# copy
- subprocess.check_call(self.s3ql_cmd_argv('s3qlcp') +
+ subprocess.check_call(self.s3ql_cmd_argv('s3qlcp') +
[ '--quiet', os.path.join(self.mnt_dir, 'orig'),
os.path.join(self.mnt_dir, 'copy')])
@@ -55,10 +55,9 @@ class cpTests(t4_fuse.fuse_tests):
universal_newlines=True, stderr=subprocess.STDOUT)
except CalledProcessError as exc:
self.fail('rsync failed with ' + exc.output)
-
+
if out:
self.fail('Copy not equal to original, rsync says:\n' + out)
finally:
shutil.rmtree(tempdir)
-
diff --git a/tests/t5_failsafe.py b/tests/t5_failsafe.py
index b221859..6a30352 100755
--- a/tests/t5_failsafe.py
+++ b/tests/t5_failsafe.py
@@ -17,11 +17,11 @@ import t4_fuse
import s3ql.ctrl
import pytest
import errno
-from common import get_remote_test_info
+from common import get_remote_test_info, NoTestSection
from s3ql.backends import gs
from argparse import Namespace
from s3ql.common import BUFSIZE
-from s3ql.backends.common import get_ssl_context
+from s3ql.common import get_ssl_context
class FailsafeTest(t4_fuse.fuse_tests):
'''
@@ -32,11 +32,15 @@ class FailsafeTest(t4_fuse.fuse_tests):
We use Google Storage, so that we don't have to worry about
propagation delays.
'''
-
+
def setUp(self):
super().setUp()
- (backend_login, backend_pw,
- self.storage_url) = get_remote_test_info('gs-test', self.skipTest)
+ try:
+ (backend_login, backend_pw,
+ self.storage_url) = get_remote_test_info('gs-test')
+ except NoTestSection as exc:
+ self.skipTest(exc.reason)
+
self.backend_login = backend_login
self.backend_passphrase = backend_pw
@@ -61,7 +65,7 @@ class FailsafeTest(t4_fuse.fuse_tests):
for _ in range(5):
fh.write(src.read(BUFSIZE))
s3ql.ctrl.main(['flushcache', self.mnt_dir])
-
+
with open(fname2, 'w') as fh:
fh.write('Hello, second world')
s3ql.ctrl.main(['flushcache', self.mnt_dir])
@@ -79,7 +83,7 @@ class FailsafeTest(t4_fuse.fuse_tests):
with open(fname1, 'rb') as fh:
fh.read()
assert exc_info.value.errno == errno.EIO
-
+
# This should still work
with open(fname2, 'rb') as fh:
fh.read()
@@ -87,5 +91,3 @@ class FailsafeTest(t4_fuse.fuse_tests):
# But this should not
with pytest.raises(PermissionError):
open(fname2, 'wb')
-
-
diff --git a/tests/t5_full.py b/tests/t5_full.py
index b02e577..0148ffb 100755
--- a/tests/t5_full.py
+++ b/tests/t5_full.py
@@ -12,7 +12,7 @@ if __name__ == '__main__':
import sys
sys.exit(pytest.main([__file__] + sys.argv[1:]))
-from common import populate_dir, skip_without_rsync, get_remote_test_info
+from common import populate_dir, skip_without_rsync, get_remote_test_info, NoTestSection
import shutil
import subprocess
from subprocess import check_output, CalledProcessError
@@ -26,14 +26,14 @@ class FullTest(t4_fuse.fuse_tests):
def populate_dir(self, path):
populate_dir(path)
-
+
def runTest(self):
skip_without_rsync()
ref_dir = tempfile.mkdtemp(prefix='s3ql-ref-')
try:
self.populate_dir(ref_dir)
-
+
# Copy source data
self.mkfs()
self.mount()
@@ -71,8 +71,11 @@ class FullTest(t4_fuse.fuse_tests):
class RemoteTest:
def setUp(self, name):
super().setUp()
- (backend_login, backend_pw,
- self.storage_url) = get_remote_test_info(name, self.skipTest)
+ try:
+ (backend_login, backend_pw,
+ self.storage_url) = get_remote_test_info(name)
+ except NoTestSection as exc:
+ self.skipTest(exc.reason)
self.backend_login = backend_login
self.backend_passphrase = backend_pw
@@ -81,8 +84,8 @@ class RemoteTest:
def tearDown(self):
super().tearDown()
-
- proc = subprocess.Popen(self.s3ql_cmd_argv('s3qladm') +
+
+ proc = subprocess.Popen(self.s3ql_cmd_argv('s3qladm') +
[ '--quiet', '--authfile', '/dev/null', '--fatal-warnings',
'clear', self.storage_url ],
stdin=subprocess.PIPE, universal_newlines=True)
@@ -94,7 +97,7 @@ class RemoteTest:
self.assertEqual(proc.wait(), 0)
-
+
class S3FullTest(RemoteTest, FullTest):
def setUp(self):
super().setUp('s3-test')
diff --git a/tests/t6_upgrade.py b/tests/t6_upgrade.py
index cc768a6..e530e29 100755
--- a/tests/t6_upgrade.py
+++ b/tests/t6_upgrade.py
@@ -13,7 +13,7 @@ if __name__ == '__main__':
sys.exit(pytest.main([__file__] + sys.argv[1:]))
from common import populate_dir, skip_without_rsync, retry
-from t1_backends import get_remote_test_info
+from t1_backends import get_remote_test_info, NoTestSection
import shutil
import subprocess
from subprocess import check_output, CalledProcessError
@@ -38,7 +38,7 @@ class UpgradeTest(t4_fuse.fuse_tests):
self.ref_dir = tempfile.mkdtemp(prefix='s3ql-ref-')
self.bak_dir = tempfile.mkdtemp(prefix='s3ql-bak-')
self.basedir_old = basedir_old
-
+
def tearDown(self):
super().tearDown()
shutil.rmtree(self.ref_dir)
@@ -90,7 +90,7 @@ class UpgradeTest(t4_fuse.fuse_tests):
self.assertFalse(os.path.ismount(self.mnt_dir))
def upgrade(self):
- proc = subprocess.Popen(self.s3ql_cmd_argv('s3qladm') +
+ proc = subprocess.Popen(self.s3ql_cmd_argv('s3qladm') +
[ '--fatal-warnings', '--cachedir', self.cache_dir, '--authfile',
'/dev/null', '--quiet', 'upgrade', self.storage_url ],
stdin=subprocess.PIPE, universal_newlines=True)
@@ -105,7 +105,7 @@ class UpgradeTest(t4_fuse.fuse_tests):
self.assertEqual(proc.wait(), 0)
def compare(self):
-
+
# Compare
self.fsck()
self.mount()
@@ -119,7 +119,7 @@ class UpgradeTest(t4_fuse.fuse_tests):
self.fail('Copy not equal to original, rsync says:\n' + out)
self.umount()
-
+
def runTest(self):
populate_dir(self.ref_dir)
@@ -150,11 +150,14 @@ class UpgradeTest(t4_fuse.fuse_tests):
class RemoteUpgradeTest:
def setUp(self, name):
super().setUp()
- (backend_login, backend_pw,
- self.storage_url) = get_remote_test_info(name, self.skipTest)
+ try:
+ (backend_login, backend_pw,
+ self.storage_url) = get_remote_test_info(name)
+ except NoTestSection as exc:
+ self.skipTest(exc.reason)
self.backend_login = backend_login
self.backend_passphrase = backend_pw
-
+
def runTest(self):
populate_dir(self.ref_dir, entries=50, size=5*1024*1024)
@@ -172,7 +175,7 @@ class RemoteUpgradeTest:
def tearDown(self):
super().tearDown()
-
+
proc = subprocess.Popen(self.s3ql_cmd_argv('s3qladm') +
[ '--quiet', '--authfile', '/dev/null', '--fatal-warnings',
'clear', self.storage_url ],
@@ -192,4 +195,3 @@ class S3UpgradeTest(RemoteUpgradeTest, UpgradeTest):
class SwiftUpgradeTest(RemoteUpgradeTest, UpgradeTest):
def setUp(self):
super().setUp('swift-test')
-
diff --git a/tests/test.log b/tests/test.log
deleted file mode 100644
index e69de29..0000000
--- a/tests/test.log
+++ /dev/null
diff --git a/tests/test_crit.log b/tests/test_crit.log
deleted file mode 100644
index e69de29..0000000
--- a/tests/test_crit.log
+++ /dev/null
diff --git a/util/cmdline_lexer.py b/util/cmdline_lexer.py
index b2fdda4..d973e4d 100644
--- a/util/cmdline_lexer.py
+++ b/util/cmdline_lexer.py
@@ -29,4 +29,3 @@ class CommandLineLexer(RegexLexer):
],
}
-
diff --git a/util/sphinx_pipeinclude.py b/util/sphinx_pipeinclude.py
index a02ecea..4f9c73b 100644
--- a/util/sphinx_pipeinclude.py
+++ b/util/sphinx_pipeinclude.py
@@ -29,10 +29,10 @@ class PipeInclude(Include):
command = self.arguments[0]
command_list = shlex.split(command)
-
+
if command_list[0] == 'python':
command_list[0] = sys.executable
-
+
encoding = self.options.get(
'encoding', self.state.document.settings.input_encoding)
tab_width = self.options.get(
@@ -104,4 +104,3 @@ class PipeInclude(Include):
def setup(app):
app.add_directive('pipeinclude', PipeInclude)
-