~akopytov/percona-xtrabackup/bug1166888-2.0

« back to all changes in this revision

Viewing changes to src/libarchive/libarchive/test/test_write_format_cpio_odc.c

  • Committer: Alexey Kopytov
  • Date: 2012-02-10 20:05:56 UTC
  • mto: This revision was merged to the branch mainline in revision 390.
  • Revision ID: akopytov@gmail.com-20120210200556-6kx41z8wwrqfucro
Rebase of the parallel compression patch on new trunk + post-review
fixes.

Implementation of parallel compression and streaming for XtraBackup.

This revision implements the following changes:

* InnoDB files are now streamed by the xtrabackup binary rather than
innobackupex. As a result, integrity is now verified by xtrabackup and
thus tar4ibd is no longer needed, so it was removed.

* xtrabackup binary now accepts the new '--stream' option which has
exactly the same semantics as the '--stream' option in
innobackupex: it tells xtrabackup to stream all files to the standard
output in the specified format rather than storing them locally.

* The xtrabackup binary can now do parallel compression using the
quicklz library. Two new options were added to xtrabackup to support
this feature:

- '--compress' tells xtrabackup to compress all output data, including
the transaction log file and meta data files, using the specified
compression algorithm. The only currently supported algorithm is
'quicklz'. The resulting files have the qpress archive format,
i.e. every *.qp file produced by xtrabackup is essentially a one-file
qpress archive and can be extracted and uncompressed by the qpress
file archiver (http://www.quicklz.com/).

- '--compress-threads' specifies the number of worker threads used by
xtrabackup for parallel data compression. This option defaults to 1.

Parallel compression ('--compress-threads') can be used together with
parallel file copying ('--parallel'). For example, '--parallel=4
--compress --compress-threads=2' will create 4 IO threads that will
read the data and pipe it to 2 compression threads.

* To support simultaneous compression and streaming, a new custom
streaming format called 'xbstream' was introduced to XtraBackup in
addition to the 'tar' format. That was required to overcome some
limitations of traditional archive formats such as 'tar', 'cpio' and
others that do not allow streaming dynamically generated files, for
example dynamically compressed files.  Other advantages of xbstream over
traditional streaming/archive formats include ability to stream multiple
files concurrently (so it is possible to use streaming in the xbstream
format together with the --parallel option) and more compact data
storage.

* To allow streaming and extracting files to/from the xbstream format
produced by xtrabackup, a new utility aptly called 'xbstream' was
added to the XtraBackup distribution. This utility has a tar-like
interface:

- with the '-x' option it extracts files from the stream read from its
standard input to the current directory unless specified otherwise
with the '-C' option.

- with the '-c' option it streams files specified on the command line
to its standard output.

The utility also tries to minimize its impact on the OS page cache by
using the appropriate posix_fadvise() calls when available.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2003-2007 Tim Kientzle
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 *
 
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 
15
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
16
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
17
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 
18
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
19
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
23
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
24
 */
 
25
#include "test.h"
 
26
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_cpio_odc.c 201247 2009-12-30 05:59:21Z kientzle $");
 
27
 
 
28
 
 
29
static int
 
30
is_octal(const char *p, size_t l)
 
31
{
 
32
        while (l > 0) {
 
33
                if (*p < '0' || *p > '7')
 
34
                        return (0);
 
35
                --l;
 
36
                ++p;
 
37
        }
 
38
        return (1);
 
39
}
 
40
 
 
41
/*
 
42
 * Detailed verification that cpio 'odc' archives are written with
 
43
 * the correct format.
 
44
 */
 
45
DEFINE_TEST(test_write_format_cpio_odc)
 
46
{
 
47
        struct archive *a;
 
48
        struct archive_entry *entry;
 
49
        char *buff, *e, *file;
 
50
        size_t buffsize = 100000;
 
51
        size_t used;
 
52
 
 
53
        buff = malloc(buffsize);
 
54
 
 
55
        /* Create a new archive in memory. */
 
56
        assert((a = archive_write_new()) != NULL);
 
57
        assertEqualIntA(a, 0, archive_write_set_format_cpio(a));
 
58
        assertEqualIntA(a, 0, archive_write_set_compression_none(a));
 
59
        assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used));
 
60
 
 
61
        /*
 
62
         * Add various files to it.
 
63
         * TODO: Extend this to cover more filetypes.
 
64
         */
 
65
 
 
66
        /* "file" with 10 bytes of content */
 
67
        assert((entry = archive_entry_new()) != NULL);
 
68
        archive_entry_set_mtime(entry, 1, 10);
 
69
        archive_entry_set_pathname(entry, "file");
 
70
        archive_entry_set_mode(entry, S_IFREG | 0664);
 
71
        archive_entry_set_size(entry, 10);
 
72
        archive_entry_set_uid(entry, 80);
 
73
        archive_entry_set_gid(entry, 90);
 
74
        archive_entry_set_dev(entry, 12);
 
75
        archive_entry_set_ino(entry, 89);
 
76
        archive_entry_set_nlink(entry, 2);
 
77
        assertEqualIntA(a, 0, archive_write_header(a, entry));
 
78
        archive_entry_free(entry);
 
79
        assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10));
 
80
 
 
81
        /* Hardlink to "file" with 10 bytes of content */
 
82
        assert((entry = archive_entry_new()) != NULL);
 
83
        archive_entry_set_mtime(entry, 1, 10);
 
84
        archive_entry_set_pathname(entry, "linkfile");
 
85
        archive_entry_set_mode(entry, S_IFREG | 0664);
 
86
        archive_entry_set_size(entry, 10);
 
87
        archive_entry_set_uid(entry, 80);
 
88
        archive_entry_set_gid(entry, 90);
 
89
        archive_entry_set_dev(entry, 12);
 
90
        archive_entry_set_ino(entry, 89);
 
91
        archive_entry_set_nlink(entry, 2);
 
92
        assertEqualIntA(a, 0, archive_write_header(a, entry));
 
93
        archive_entry_free(entry);
 
94
        assertEqualIntA(a, 10, archive_write_data(a, "1234567890", 10));
 
95
 
 
96
        /* "dir" */
 
97
        assert((entry = archive_entry_new()) != NULL);
 
98
        archive_entry_set_mtime(entry, 2, 20);
 
99
        archive_entry_set_pathname(entry, "dir");
 
100
        archive_entry_set_mode(entry, S_IFDIR | 0775);
 
101
        archive_entry_set_size(entry, 10);
 
102
        archive_entry_set_nlink(entry, 2);
 
103
        assertEqualIntA(a, 0, archive_write_header(a, entry));
 
104
        archive_entry_free(entry);
 
105
        /* Write of data to dir should fail == zero bytes get written. */
 
106
        assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));
 
107
 
 
108
        /* "symlink" pointing to "file" */
 
109
        assert((entry = archive_entry_new()) != NULL);
 
110
        archive_entry_set_mtime(entry, 3, 30);
 
111
        archive_entry_set_pathname(entry, "symlink");
 
112
        archive_entry_set_mode(entry, 0664);
 
113
        archive_entry_set_filetype(entry, AE_IFLNK);
 
114
        archive_entry_set_symlink(entry,"file");
 
115
        archive_entry_set_size(entry, 0);
 
116
        archive_entry_set_uid(entry, 88);
 
117
        archive_entry_set_gid(entry, 98);
 
118
        archive_entry_set_dev(entry, 12);
 
119
        archive_entry_set_ino(entry, 90);
 
120
        archive_entry_set_nlink(entry, 1);
 
121
        assertEqualIntA(a, 0, archive_write_header(a, entry));
 
122
        archive_entry_free(entry);
 
123
        /* Write of data to symlink should fail == zero bytes get written. */
 
124
        assertEqualIntA(a, 0, archive_write_data(a, "1234567890", 10));
 
125
 
 
126
#if ARCHIVE_VERSION_NUMBER < 2000000
 
127
        archive_write_finish(a);
 
128
#else
 
129
        assert(0 == archive_write_finish(a));
 
130
#endif
 
131
 
 
132
        /*
 
133
         * Verify the archive format.
 
134
         *
 
135
         * Notes on the ino validation: cpio does not actually require
 
136
         * that the ino values written to the archive match those read
 
137
         * from disk.  It really requires that:
 
138
         *   * matching non-zero ino values be written as matching
 
139
         *     non-zero values
 
140
         *   * non-matching non-zero ino values be written as non-matching
 
141
         *     non-zero values
 
142
         * Libarchive further ensures that zero ino values get written
 
143
         * as zeroes.  This allows the cpio writer to generate
 
144
         * synthetic ino values for the archive that may be different
 
145
         * than those on disk in order to avoid problems due to truncation.
 
146
         * This is especially needed for odc (POSIX format) that
 
147
         * only supports 18-bit ino values.
 
148
         */
 
149
        e = buff;
 
150
 
 
151
        /* "file" */
 
152
        file = e; /* Remember where this starts... */
 
153
        assert(is_octal(e, 76)); /* Entire header is octal digits. */
 
154
        assertEqualMem(e + 0, "070707", 6); /* Magic */
 
155
        assertEqualMem(e + 6, "000014", 6); /* dev */
 
156
        assert(memcmp(e + 12, "000000", 6) != 0); /* ino must be != 0 */
 
157
        assertEqualMem(e + 18, "100664", 6); /* Mode */
 
158
        assertEqualMem(e + 24, "000120", 6); /* uid */
 
159
        assertEqualMem(e + 30, "000132", 6); /* gid */
 
160
        assertEqualMem(e + 36, "000002", 6); /* nlink */
 
161
        assertEqualMem(e + 42, "000000", 6); /* rdev */
 
162
        assertEqualMem(e + 48, "00000000001", 11); /* mtime */
 
163
        assertEqualMem(e + 59, "000005", 6); /* Name size */
 
164
        assertEqualMem(e + 65, "00000000012", 11); /* File size */
 
165
        assertEqualMem(e + 76, "file\0", 5); /* Name contents */
 
166
        assertEqualMem(e + 81, "1234567890", 10); /* File contents */
 
167
        e += 91;
 
168
 
 
169
        /* hardlink to "file" */
 
170
        assert(is_octal(e, 76)); /* Entire header is octal digits. */
 
171
        assertEqualMem(e + 0, "070707", 6); /* Magic */
 
172
        assertEqualMem(e + 6, "000014", 6); /* dev */
 
173
        assertEqualMem(e + 12, file + 12, 6); /* ino must match above */
 
174
        assertEqualMem(e + 18, "100664", 6); /* Mode */
 
175
        assertEqualMem(e + 24, "000120", 6); /* uid */
 
176
        assertEqualMem(e + 30, "000132", 6); /* gid */
 
177
        assertEqualMem(e + 36, "000002", 6); /* nlink */
 
178
        assertEqualMem(e + 42, "000000", 6); /* rdev */
 
179
        assertEqualMem(e + 48, "00000000001", 11); /* mtime */
 
180
        assertEqualMem(e + 59, "000011", 6); /* Name size */
 
181
        assertEqualMem(e + 65, "00000000012", 11); /* File size */
 
182
        assertEqualMem(e + 76, "linkfile\0", 9); /* Name contents */
 
183
        assertEqualMem(e + 85, "1234567890", 10); /* File contents */
 
184
        e += 95;
 
185
 
 
186
        /* "dir" */
 
187
        assert(is_octal(e, 76));
 
188
        assertEqualMem(e + 0, "070707", 6); /* Magic */
 
189
        assertEqualMem(e + 6, "000000", 6); /* dev */
 
190
        assertEqualMem(e + 12, "000000", 6); /* ino */
 
191
        assertEqualMem(e + 18, "040775", 6); /* Mode */
 
192
        assertEqualMem(e + 24, "000000", 6); /* uid */
 
193
        assertEqualMem(e + 30, "000000", 6); /* gid */
 
194
        assertEqualMem(e + 36, "000002", 6); /* Nlink */
 
195
        assertEqualMem(e + 42, "000000", 6); /* rdev */
 
196
        assertEqualMem(e + 48, "00000000002", 11); /* mtime */
 
197
        assertEqualMem(e + 59, "000004", 6); /* Name size */
 
198
        assertEqualMem(e + 65, "00000000000", 11); /* File size */
 
199
        assertEqualMem(e + 76, "dir\0", 4); /* name */
 
200
        e += 80;
 
201
 
 
202
        /* "symlink" pointing to "file" */
 
203
        assert(is_octal(e, 76)); /* Entire header is octal digits. */
 
204
        assertEqualMem(e + 0, "070707", 6); /* Magic */
 
205
        assertEqualMem(e + 6, "000014", 6); /* dev */
 
206
        assert(memcmp(e + 12, file + 12, 6) != 0); /* ino must != file ino */
 
207
        assert(memcmp(e + 12, "000000", 6) != 0); /* ino must != 0 */
 
208
        assertEqualMem(e + 18, "120664", 6); /* Mode */
 
209
        assertEqualMem(e + 24, "000130", 6); /* uid */
 
210
        assertEqualMem(e + 30, "000142", 6); /* gid */
 
211
        assertEqualMem(e + 36, "000001", 6); /* nlink */
 
212
        assertEqualMem(e + 42, "000000", 6); /* rdev */
 
213
        assertEqualMem(e + 48, "00000000003", 11); /* mtime */
 
214
        assertEqualMem(e + 59, "000010", 6); /* Name size */
 
215
        assertEqualMem(e + 65, "00000000004", 11); /* File size */
 
216
        assertEqualMem(e + 76, "symlink\0", 8); /* Name contents */
 
217
        assertEqualMem(e + 84, "file", 4); /* File contents == link target */
 
218
        e += 88;
 
219
 
 
220
        /* TODO: Verify other types of entries. */
 
221
 
 
222
        /* Last entry is end-of-archive marker. */
 
223
        assert(is_octal(e, 76));
 
224
        assertEqualMem(e + 0, "070707", 6); /* Magic */
 
225
        assertEqualMem(e + 6, "000000", 6); /* dev */
 
226
        assertEqualMem(e + 12, "000000", 6); /* ino */
 
227
        assertEqualMem(e + 18, "000000", 6); /* Mode */
 
228
        assertEqualMem(e + 24, "000000", 6); /* uid */
 
229
        assertEqualMem(e + 30, "000000", 6); /* gid */
 
230
        assertEqualMem(e + 36, "000001", 6); /* Nlink */
 
231
        assertEqualMem(e + 42, "000000", 6); /* rdev */
 
232
        assertEqualMem(e + 48, "00000000000", 11); /* mtime */
 
233
        assertEqualMem(e + 59, "000013", 6); /* Name size */
 
234
        assertEqualMem(e + 65, "00000000000", 11); /* File size */
 
235
        assertEqualMem(e + 76, "TRAILER!!!\0", 11); /* Name */
 
236
        e += 87;
 
237
 
 
238
        assertEqualInt((int)used, e - buff);
 
239
 
 
240
        free(buff);
 
241
}