Drizzled Public API Documentation

engine.cc
00001 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2010 Brian Aker
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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   // No catalog file, no love from us.
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     //@todo If this happens, we want a report of it. For the moment I dump
00084     //to stderr so I can catch it in Hudson.
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     Pass an empty file name, and the database options file name as extension
00216     to avoid table name to file name encoding.
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 } /* namespace catalog */
00248 } /* namespace plugin */