00001 00004 /* Copyright (C) 2007,2008,2009 Olly Betts 00005 * Copyright (C) 2008 Lemur Consulting Ltd 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License as 00009 * published by the Free Software Foundation; either version 2 of the 00010 * License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include <config.h> 00023 00024 #include "backendmanager_multi.h" 00025 00026 #include "index_utils.h" 00027 #include "str.h" 00028 #include "utils.h" 00029 00030 #include <cstdio> // For rename(). 00031 #include <cstring> 00032 #include "safeerrno.h" 00033 00034 using namespace std; 00035 00036 BackendManagerMulti::BackendManagerMulti(const std::string & subtype_) 00037 : subtype(subtype_) 00038 { 00039 if (!(false 00040 #ifdef XAPIAN_HAS_BRASS_BACKEND 00041 || subtype == "brass" 00042 #endif 00043 #ifdef XAPIAN_HAS_CHERT_BACKEND 00044 || subtype == "chert" 00045 #endif 00046 #ifdef XAPIAN_HAS_FLINT_BACKEND 00047 || subtype == "flint" 00048 #endif 00049 )) { 00050 throw ("Unknown backend type \"" + subtype + "\" specified for multi database subdatabases"); 00051 } 00052 } 00053 00054 std::string 00055 BackendManagerMulti::get_dbtype() const 00056 { 00057 return "multi_" + subtype; 00058 } 00059 00060 #define NUMBER_OF_SUB_DBS 2 00061 00062 string 00063 BackendManagerMulti::createdb_multi(const vector<string> & files) 00064 { 00065 string dbdir = ".multi" + subtype; 00066 create_dir_if_needed(dbdir); 00067 00068 string dbname = "db"; 00069 vector<string>::const_iterator i; 00070 for (i = files.begin(); i != files.end(); ++i) { 00071 dbname += "__"; 00072 dbname += *i; 00073 } 00074 string dbpath = dbdir + "/" + dbname; 00075 00076 if (file_exists(dbpath)) return dbpath; 00077 00078 string tmpfile = dbpath; 00079 tmpfile += ".tmp"; 00080 ofstream out(tmpfile.c_str()); 00081 if (!out.is_open()) { 00082 string msg = "Couldn't create file '"; 00083 msg += tmpfile; 00084 msg += "' ("; 00085 msg += strerror(errno); 00086 msg += ')'; 00087 throw msg; 00088 } 00089 00090 // Open NUMBER_OF_SUB_DBS databases and index files to the alternately so a 00091 // multi-db combining them contains the documents in the expected order. 00092 Xapian::WritableDatabase dbs[NUMBER_OF_SUB_DBS]; 00093 for (size_t n = 0; n < NUMBER_OF_SUB_DBS; ++n) { 00094 string subdbdir = dbname; 00095 subdbdir += "___"; 00096 subdbdir += str(n); 00097 #if defined XAPIAN_HAS_BRASS_BACKEND 00098 if (subtype == "brass") { 00099 dbs[n] = Xapian::Brass::open(dbdir + "/" + subdbdir, Xapian::DB_CREATE_OR_OVERWRITE); 00100 out << "brass " << subdbdir << '\n'; 00101 } 00102 #endif 00103 #if defined XAPIAN_HAS_CHERT_BACKEND 00104 if (subtype == "chert") { 00105 dbs[n] = Xapian::Chert::open(dbdir + "/" + subdbdir, Xapian::DB_CREATE_OR_OVERWRITE); 00106 out << "chert " << subdbdir << '\n'; 00107 } 00108 #endif 00109 #ifdef XAPIAN_HAS_FLINT_BACKEND 00110 if (subtype == "flint") { 00111 dbs[n] = Xapian::Flint::open(dbdir + "/" + subdbdir, Xapian::DB_CREATE_OR_OVERWRITE); 00112 out << "flint " << subdbdir << '\n'; 00113 } 00114 #endif 00115 00116 } 00117 out.close(); 00118 00119 size_t c = 0; 00120 FileIndexer f(get_datadir(), files); 00121 while (f) { 00122 dbs[c].add_document(f.next()); 00123 c = (c + 1) % NUMBER_OF_SUB_DBS; 00124 } 00125 00126 rename(tmpfile.c_str(), dbpath.c_str()); 00127 00128 return dbpath; 00129 } 00130 00131 string 00132 BackendManagerMulti::do_get_database_path(const vector<string> & files) 00133 { 00134 return createdb_multi(files); 00135 } 00136 00137 Xapian::WritableDatabase 00138 BackendManagerMulti::get_writable_database(const string &, const string &) 00139 { 00140 throw Xapian::UnimplementedError("Multi-databases don't support writing"); 00141 }