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 <drizzled/display.h>
00028 #include <google/protobuf/io/zero_copy_stream.h>
00029 #include <google/protobuf/io/zero_copy_stream_impl.h>
00030 
00031 #include <iostream>
00032 #include <fstream>
00033 #include <string>
00034 
00035 #include <drizzled/data_home.h>
00036 #include <drizzled/cached_directory.h>
00037 #include <drizzled/catalog/local.h>
00038 #include <plugin/catalog/module.h>
00039 
00040 namespace plugin {
00041 namespace catalog {
00042 
00043 static std::string CATALOG_OPT_EXT(".cat");
00044 
00045 bool Engine::create(const drizzled::identifier::Catalog &identifier, drizzled::message::catalog::shared_ptr &message)
00046 {
00047   if (mkdir(identifier.getPath().c_str(), 0777) == -1)
00048     return false;
00049 
00050   if (not writeFile(identifier, message))
00051   {
00052     rmdir(identifier.getPath().c_str());
00053 
00054     return false;
00055   }
00056 
00057   return true;
00058 }
00059 
00060 bool Engine::drop(const drizzled::identifier::Catalog &identifier)
00061 {
00062   std::string file(identifier.getPath());
00063   file.append(1, FN_LIBCHAR);
00064   file.append(CATALOG_OPT_EXT);
00065 
00066   // No catalog file, no love from us.
00067   if (access(file.c_str(), F_OK))
00068   {
00069     perror(file.c_str());
00070     return false;
00071   }
00072 
00073   if (unlink(file.c_str()))
00074   {
00075     perror(file.c_str());
00076     return false;
00077   }
00078 
00079   if (rmdir(identifier.getPath().c_str()))
00080   {
00081     perror(identifier.getPath().c_str());
00082     //@todo If this happens, we want a report of it. For the moment I dump
00083     //to stderr so I can catch it in Hudson.
00084     drizzled::CachedDirectory dir(identifier.getPath());
00085   }
00086 
00087   return true;
00088 }
00089 
00090 void Engine::getMessages(drizzled::message::catalog::vector &messages)
00091 {
00092   prime(messages);
00093 }
00094 
00095 drizzled::message::catalog::shared_ptr Engine::getMessage(drizzled::identifier::Catalog::const_reference identifier)
00096 {
00097   if (drizzled::catalog::local_identifier() == identifier)
00098   {
00099     return drizzled::message::catalog::make_shared(identifier);
00100   }
00101 
00102   drizzled::message::catalog::shared_ptr message;
00103   if ((message= readFile(identifier)))
00104   {
00105     assert(message);
00106     return message;
00107   }
00108 
00109   return drizzled::message::catalog::shared_ptr();
00110 }
00111 
00112 void Engine::prime(drizzled::message::catalog::vector &messages)
00113 {
00114   bool found_local= false;
00115   drizzled::CachedDirectory directory(drizzled::getFullDataHome().file_string(), drizzled::CachedDirectory::DIRECTORY, true);
00116   drizzled::CachedDirectory::Entries files= directory.getEntries();
00117 
00118 
00119   for (drizzled::CachedDirectory::Entries::iterator fileIter= files.begin();
00120        fileIter != files.end(); fileIter++)
00121   {
00122     drizzled::CachedDirectory::Entry *entry= *fileIter;
00123     drizzled::message::catalog::shared_ptr message;
00124 
00125     if (not entry->filename.compare(GLOBAL_TEMPORARY_EXT))
00126       continue;
00127 
00128     drizzled::identifier::Catalog identifier(entry->filename);
00129 
00130     if (message= readFile(identifier))
00131     {
00132       messages.push_back(message);
00133 
00134       if (drizzled::catalog::local_identifier() == identifier)
00135         found_local= true;
00136     }
00137   }
00138 
00139   if (not found_local)
00140   {
00141     messages.push_back(drizzled::catalog::local()->message());
00142   }
00143 }
00144 
00145 bool Engine::writeFile(const drizzled::identifier::Catalog &identifier, drizzled::message::catalog::shared_ptr &message)
00146 {
00147   char file_tmp[FN_REFLEN];
00148   std::string file(identifier.getPath());
00149 
00150 
00151   file.append(1, FN_LIBCHAR);
00152   file.append(CATALOG_OPT_EXT);
00153 
00154   snprintf(file_tmp, FN_REFLEN, "%sXXXXXX", file.c_str());
00155 
00156   int fd= mkstemp(file_tmp);
00157 
00158   if (fd == -1)
00159   {
00160     perror(file_tmp);
00161 
00162     return false;
00163   }
00164 
00165   bool success;
00166 
00167   try {
00168     success= message->SerializeToFileDescriptor(fd);
00169   }
00170   catch (...)
00171   {
00172     success= false;
00173   }
00174 
00175   if (not success)
00176   {
00177     drizzled::my_error(drizzled::ER_CORRUPT_CATALOG_DEFINITION, MYF(0), file.c_str(),
00178                        message->InitializationErrorString().empty() ? "unknown" :  message->InitializationErrorString().c_str());
00179 
00180     if (close(fd) == -1)
00181       perror(file_tmp);
00182 
00183     if (unlink(file_tmp))
00184       perror(file_tmp);
00185 
00186     return false;
00187   }
00188 
00189   if (close(fd) == -1)
00190   {
00191     perror(file_tmp);
00192 
00193     if (unlink(file_tmp))
00194       perror(file_tmp);
00195 
00196     return false;
00197   }
00198 
00199   if (rename(file_tmp, file.c_str()) == -1)
00200   {
00201     if (unlink(file_tmp))
00202       perror(file_tmp);
00203 
00204     return false;
00205   }
00206 
00207   return true;
00208 }
00209 
00210 
00211 drizzled::message::catalog::shared_ptr Engine::readFile(drizzled::identifier::Catalog::const_reference identifier)
00212 {
00213   std::string path(identifier.getPath());
00214 
00215   /*
00216     Pass an empty file name, and the database options file name as extension
00217     to avoid table name to file name encoding.
00218   */
00219   path.append(1, FN_LIBCHAR);
00220   path.append(CATALOG_OPT_EXT);
00221 
00222   std::fstream input(path.c_str(), std::ios::in | std::ios::binary);
00223 
00224   if (input.good())
00225   {
00226     drizzled::message::catalog::shared_ptr message= drizzled::message::catalog::make_shared(identifier);
00227 
00228     if (not message)
00229       return drizzled::message::catalog::shared_ptr();
00230 
00231 
00232     if (message->ParseFromIstream(&input))
00233     {
00234       return message;
00235     }
00236 
00237     drizzled::my_error(drizzled::ER_CORRUPT_CATALOG_DEFINITION, MYF(0), path.c_str(),
00238                        message->InitializationErrorString().empty() ? "unknown" :  message->InitializationErrorString().c_str());
00239   }
00240   else
00241   {
00242     perror(path.c_str());
00243   }
00244 
00245   return drizzled::message::catalog::shared_ptr();
00246 }
00247 
00248 } /* namespace catalog */
00249 } /* namespace plugin */