root / tags / 1.0.8 / xapian-core / backends / flint / flint_version.cc

Revision 10568, 4.8 kB (checked in by olly, 8 months ago)

Backport change from trunk:
backends/flint/flint_version.cc,common/stringutils.h: Move
CONST_STRLEN() into stringutils.h.

  • Property svn:eol-style set to native
Line 
1/** @file flint_version.cc
2 * @brief FlintVersion class
3 */
4/* Copyright (C) 2006,2007 Olly Betts
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19 */
20
21#include <config.h>
22
23#include "safeerrno.h"
24
25#include <xapian/error.h>
26
27#include "flint_io.h"
28#include "flint_version.h"
29#include "stringutils.h" // For STRINGIZE() and CONST_STRLEN().
30#include "utils.h"
31
32#ifdef __WIN32__
33# include "msvc_posix_wrapper.h"
34#endif
35
36#include <string>
37
38#include <string.h> // for memcmp
39
40using std::string;
41
42// YYYYMMDDX where X allows multiple format revisions in a day
43#define FLINT_VERSION 200709120
44// 200709120 1.0.3 Database::get_metadata(), WritableDatabase::set_metadata().
45//                 Kill the unused "has_termfreqs" flag in the termlist table.
46// 200706140 1.0.2 Optional value and position tables.
47// 200704230 1.0.0 Use zlib compression of tags for record and termlist tables.
48// 200611200  N/A  Fixed occasional, architecture-dependent surplus bits in
49//                 interpolative coding; "flicklock" -> "flintlock".
50// 200506110 0.9.2 Fixed interpolative coding to work(!)
51// 200505310 0.9.1 Interpolative coding for position lists.
52// 200505280  N/A  Total doclen and last docid entry moved to postlist table.
53// 200505270  N/A  First dated version.
54
55#define MAGIC_STRING "IAmFlint"
56
57#define MAGIC_LEN CONST_STRLEN(MAGIC_STRING)
58#define VERSIONFILE_SIZE (MAGIC_LEN + 4)
59
60void FlintVersion::create()
61{
62    char buf[VERSIONFILE_SIZE] = MAGIC_STRING;
63    unsigned char *v = reinterpret_cast<unsigned char *>(buf) + MAGIC_LEN;
64    v[0] = static_cast<unsigned char>(FLINT_VERSION & 0xff);
65    v[1] = static_cast<unsigned char>((FLINT_VERSION >> 8) & 0xff);
66    v[2] = static_cast<unsigned char>((FLINT_VERSION >> 16) & 0xff);
67    v[3] = static_cast<unsigned char>((FLINT_VERSION >> 24) & 0xff);
68
69    int fd = ::open(filename.c_str(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
70
71    if (fd < 0) {
72        string msg("Failed to create flint version file: ");
73        msg += filename;
74        throw Xapian::DatabaseOpeningError(msg, errno);
75    }
76
77    try {
78        flint_io_write(fd, buf, VERSIONFILE_SIZE);
79    } catch (...) {
80        (void)close(fd);
81        throw;
82    }
83
84    if (close(fd) != 0) {
85        string msg("Failed to create flint version file: ");
86        msg += filename;
87        throw Xapian::DatabaseOpeningError(msg, errno);
88    }
89}
90
91void FlintVersion::read_and_check(bool readonly)
92{
93    int fd = ::open(filename.c_str(), O_RDONLY|O_BINARY);
94
95    if (fd < 0) {
96        string msg("Failed to open flint version file for reading: ");
97        msg += filename;
98        throw Xapian::DatabaseOpeningError(msg, errno);
99    }
100
101    // Try to read an extra byte so we know if the file is too long.
102    char buf[VERSIONFILE_SIZE + 1];
103    size_t size;
104    try {
105        size = flint_io_read(fd, buf, VERSIONFILE_SIZE + 1, 0);
106    } catch (...) {
107        (void)close(fd);
108        throw;
109    }
110    (void)close(fd);
111
112    if (size != VERSIONFILE_SIZE) {
113        string msg("Flint version file ");
114        msg += filename;
115        msg += " should be "STRINGIZE(VERSIONFILE_SIZE)" bytes, actually ";
116        msg += om_tostring(size);
117        throw Xapian::DatabaseCorruptError(msg);
118    }
119
120    if (memcmp(buf, MAGIC_STRING, MAGIC_LEN) != 0) {
121        string msg("Flint version file doesn't contain the right magic string: ");
122        msg += filename;
123        throw Xapian::DatabaseCorruptError(msg);
124    }
125
126    const unsigned char *v;
127    v = reinterpret_cast<const unsigned char *>(buf) + MAGIC_LEN;
128    unsigned int version = v[0] | (v[1] << 8) | (v[2] << 16) | (v[3] << 24);
129    if (version >= 200704230 && version < 200709120) {
130        if (readonly) return;
131        // Upgrade the database to the current version since any changes we
132        // make won't be compatible with older versions of Xapian.
133        string filename_save = filename;
134        filename += ".tmp";
135        create();
136        int result;
137#ifdef __WIN32__
138        result = msvc_posix_rename(filename.c_str(), filename_save.c_str());
139#else
140        result = rename(filename.c_str(), filename_save.c_str());
141#endif
142        filename = filename_save;
143        if (result == -1) {
144            string msg("Failed to update flint version file: ");
145            msg += filename;
146            throw Xapian::DatabaseOpeningError(msg);
147        }
148        return;
149    }
150    if (version != FLINT_VERSION) {
151        string msg("Flint version file ");
152        msg += filename;
153        msg += " is version ";
154        msg += om_tostring(version);
155        msg += " but I only understand "STRINGIZE(FLINT_VERSION);
156        throw Xapian::DatabaseVersionError(msg);
157    }
158}
Note: See TracBrowser for help on using the browser.