00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <fcntl.h>
00024 #include <sys/stat.h>
00025 #include <sys/types.h>
00026
00027 #include <boost/foreach.hpp>
00028 #include <drizzled/display.h>
00029 #include <google/protobuf/io/zero_copy_stream.h>
00030 #include <google/protobuf/io/zero_copy_stream_impl.h>
00031
00032 #include <iostream>
00033 #include <fstream>
00034 #include <string>
00035
00036 #include <drizzled/data_home.h>
00037 #include <drizzled/cached_directory.h>
00038 #include <drizzled/catalog/local.h>
00039 #include <plugin/catalog/module.h>
00040
00041 namespace plugin {
00042 namespace catalog {
00043
00044 static std::string CATALOG_OPT_EXT(".cat");
00045
00046 bool Engine::create(const drizzled::identifier::Catalog &identifier, drizzled::message::catalog::shared_ptr &message)
00047 {
00048 if (mkdir(identifier.getPath().c_str(), 0777) == -1)
00049 return false;
00050
00051 if (not writeFile(identifier, message))
00052 {
00053 rmdir(identifier.getPath().c_str());
00054
00055 return false;
00056 }
00057
00058 return true;
00059 }
00060
00061 bool Engine::drop(const drizzled::identifier::Catalog &identifier)
00062 {
00063 std::string file(identifier.getPath());
00064 file.append(1, FN_LIBCHAR);
00065 file.append(CATALOG_OPT_EXT);
00066
00067
00068 if (access(file.c_str(), F_OK))
00069 {
00070 perror(file.c_str());
00071 return false;
00072 }
00073
00074 if (unlink(file.c_str()))
00075 {
00076 perror(file.c_str());
00077 return false;
00078 }
00079
00080 if (rmdir(identifier.getPath().c_str()))
00081 {
00082 perror(identifier.getPath().c_str());
00083
00084
00085 drizzled::CachedDirectory dir(identifier.getPath());
00086 }
00087
00088 return true;
00089 }
00090
00091 void Engine::getMessages(drizzled::message::catalog::vector &messages)
00092 {
00093 prime(messages);
00094 }
00095
00096 drizzled::message::catalog::shared_ptr Engine::getMessage(const drizzled::identifier::Catalog& identifier)
00097 {
00098 if (drizzled::catalog::local_identifier() == identifier)
00099 {
00100 return drizzled::message::catalog::make_shared(identifier);
00101 }
00102
00103 drizzled::message::catalog::shared_ptr message;
00104 if ((message= readFile(identifier)))
00105 {
00106 assert(message);
00107 return message;
00108 }
00109
00110 return drizzled::message::catalog::shared_ptr();
00111 }
00112
00113 void Engine::prime(drizzled::message::catalog::vector &messages)
00114 {
00115 bool found_local= false;
00116 drizzled::CachedDirectory directory(drizzled::getFullDataHome().file_string(), drizzled::CachedDirectory::DIRECTORY, true);
00117 drizzled::CachedDirectory::Entries files= directory.getEntries();
00118
00119
00120 BOOST_FOREACH(drizzled::CachedDirectory::Entries::reference entry, files)
00121 {
00122 drizzled::message::catalog::shared_ptr message;
00123
00124 if (not entry->filename.compare(GLOBAL_TEMPORARY_EXT))
00125 continue;
00126
00127 drizzled::identifier::Catalog identifier(entry->filename);
00128
00129 if (message= readFile(identifier))
00130 {
00131 messages.push_back(message);
00132
00133 if (drizzled::catalog::local_identifier() == identifier)
00134 found_local= true;
00135 }
00136 }
00137
00138 if (not found_local)
00139 {
00140 messages.push_back(drizzled::catalog::local()->message());
00141 }
00142 }
00143
00144 bool Engine::writeFile(const drizzled::identifier::Catalog &identifier, drizzled::message::catalog::shared_ptr &message)
00145 {
00146 char file_tmp[FN_REFLEN];
00147 std::string file(identifier.getPath());
00148
00149
00150 file.append(1, FN_LIBCHAR);
00151 file.append(CATALOG_OPT_EXT);
00152
00153 snprintf(file_tmp, FN_REFLEN, "%sXXXXXX", file.c_str());
00154
00155 int fd= mkstemp(file_tmp);
00156
00157 if (fd == -1)
00158 {
00159 perror(file_tmp);
00160
00161 return false;
00162 }
00163
00164 bool success;
00165
00166 try {
00167 success= message->SerializeToFileDescriptor(fd);
00168 }
00169 catch (...)
00170 {
00171 success= false;
00172 }
00173
00174 if (not success)
00175 {
00176 drizzled::my_error(drizzled::ER_CORRUPT_CATALOG_DEFINITION, MYF(0), file.c_str(),
00177 message->InitializationErrorString().empty() ? "unknown" : message->InitializationErrorString().c_str());
00178
00179 if (close(fd) == -1)
00180 perror(file_tmp);
00181
00182 if (unlink(file_tmp))
00183 perror(file_tmp);
00184
00185 return false;
00186 }
00187
00188 if (close(fd) == -1)
00189 {
00190 perror(file_tmp);
00191
00192 if (unlink(file_tmp))
00193 perror(file_tmp);
00194
00195 return false;
00196 }
00197
00198 if (rename(file_tmp, file.c_str()) == -1)
00199 {
00200 if (unlink(file_tmp))
00201 perror(file_tmp);
00202
00203 return false;
00204 }
00205
00206 return true;
00207 }
00208
00209
00210 drizzled::message::catalog::shared_ptr Engine::readFile(const drizzled::identifier::Catalog& identifier)
00211 {
00212 std::string path(identifier.getPath());
00213
00214
00215
00216
00217
00218 path.append(1, FN_LIBCHAR);
00219 path.append(CATALOG_OPT_EXT);
00220
00221 std::fstream input(path.c_str(), std::ios::in | std::ios::binary);
00222
00223 if (input.good())
00224 {
00225 drizzled::message::catalog::shared_ptr message= drizzled::message::catalog::make_shared(identifier);
00226
00227 if (not message)
00228 return drizzled::message::catalog::shared_ptr();
00229
00230
00231 if (message->ParseFromIstream(&input))
00232 {
00233 return message;
00234 }
00235
00236 drizzled::my_error(drizzled::ER_CORRUPT_CATALOG_DEFINITION, MYF(0), path.c_str(),
00237 message->InitializationErrorString().empty() ? "unknown" : message->InitializationErrorString().c_str());
00238 }
00239 else
00240 {
00241 perror(path.c_str());
00242 }
00243
00244 return drizzled::message::catalog::shared_ptr();
00245 }
00246
00247 }
00248 }