Drizzled Public API Documentation

invalidator.cc
00001 /* 
00002  * Copyright (C) 2010 Djellel Eddine Difallah
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *   * Redistributions of source code must retain the above copyright notice,
00009  *     this list of conditions and the following disclaimer.
00010  *   * Redistributions in binary form must reproduce the above copyright notice,
00011  *     this list of conditions and the following disclaimer in the documentation
00012  *     and/or other materials provided with the distribution.
00013  *   * Neither the name of Djellel Eddine Difallah nor the names of its contributors
00014  *     may be used to endorse or promote products derived from this software
00015  *     without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00027  * THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include <config.h>
00031 #include "invalidator.h"
00032 #include "query_cache_service.h"
00033 #include "memcached_qc.h"
00034 
00035 #include <drizzled/session.h>
00036 #include <drizzled/message/transaction.pb.h>
00037 #include <drizzled/message/table.pb.h>
00038 #include <drizzled/message/statement_transform.h>
00039 
00040 #include <vector>
00041 #include <string>
00042 #include <algorithm>
00043 
00044 
00045 using namespace drizzled;
00046 using namespace std;
00047 
00048 Invalidator::Invalidator(string name_arg)
00049   : 
00050     plugin::TransactionApplier(name_arg)
00051 {
00052 }
00053 
00054 plugin::ReplicationReturnCode
00055 Invalidator::apply(Session &in_session, 
00056                    const message::Transaction &to_apply)
00057 {
00058   (void) in_session;
00059   string schema_name;
00060   string table_name;
00061 
00062   size_t stmt_size= to_apply.statement_size();
00063 
00064   for (size_t i= 0; i < stmt_size; i++)
00065   {
00066     schema_name.clear();
00067     table_name.clear();
00068     const message::Statement &stmt= to_apply.statement(i);
00069 
00070     /*
00071      * We don't handle raw SQL for now.
00072      */
00073     if (stmt.type() != message::Statement::RAW_SQL)
00074     {
00075       parseStatementTableMetadata(stmt, schema_name, table_name);
00076     }
00077     else
00078     {
00079       continue; /* go on to the next statement */
00080     }
00081 
00082     /* Now lets invalidate all the entries of the table */
00083     invalidateByTableName(schema_name, table_name);
00084   }
00085  return plugin::SUCCESS;
00086 }
00087 
00088 void Invalidator::parseStatementTableMetadata(const message::Statement &in_statement,
00089                                                   string &in_schema_name,
00090                                                   string &in_table_name) const
00091 {
00092   switch (in_statement.type())
00093   {
00094     case message::Statement::INSERT:
00095     {
00096       const message::TableMetadata &metadata= in_statement.insert_header().table_metadata();
00097       in_schema_name.assign(metadata.schema_name());
00098       in_table_name.assign(metadata.table_name());
00099       break;
00100     }
00101     case message::Statement::UPDATE:
00102     {
00103       const message::TableMetadata &metadata= in_statement.update_header().table_metadata();
00104       in_schema_name.assign(metadata.schema_name());
00105       in_table_name.assign(metadata.table_name());
00106       break;
00107     }
00108     case message::Statement::DELETE:
00109     {
00110       const message::TableMetadata &metadata= in_statement.delete_header().table_metadata();
00111       in_schema_name.assign(metadata.schema_name());
00112       in_table_name.assign(metadata.table_name());
00113       break;
00114     }
00115     case message::Statement::CREATE_SCHEMA:
00116     {
00117       in_schema_name.assign(in_statement.create_schema_statement().schema().name());
00118       in_table_name.clear();
00119       break;
00120     }
00121     case message::Statement::ALTER_SCHEMA:
00122     {
00123       in_schema_name.assign(in_statement.alter_schema_statement().after().name());
00124       in_table_name.clear();
00125       break;
00126     }
00127     case message::Statement::DROP_SCHEMA:
00128     {
00129       in_schema_name.assign(in_statement.drop_schema_statement().schema_name());
00130       in_table_name.clear();
00131       break;
00132     }
00133     case message::Statement::CREATE_TABLE:
00134     {
00135       in_schema_name.assign(in_statement.create_table_statement().table().schema());
00136       in_table_name.assign(in_statement.create_table_statement().table().name());
00137       break;
00138     }
00139     case message::Statement::ALTER_TABLE:
00140     {
00141       in_schema_name.assign(in_statement.alter_table_statement().before().schema());
00142       in_table_name.assign(in_statement.alter_table_statement().before().name());
00143       break;
00144     }
00145     case message::Statement::DROP_TABLE:
00146     {
00147       const message::TableMetadata &metadata= in_statement.drop_table_statement().table_metadata();
00148       in_schema_name.assign(metadata.schema_name());
00149       in_table_name.assign(metadata.table_name());
00150       break;
00151     }
00152     default:
00153     {
00154       /* All other types have no schema and table information */
00155       in_schema_name.clear();
00156       in_table_name.clear();
00157       break;
00158     }
00159   }  
00160 }
00161 void Invalidator::invalidateByTableName(const std::string &in_schema_name,
00162                                         const std::string &in_table_name) const
00163 {
00164   /* Reconstitute the schema+table key */
00165   string key= in_schema_name+in_table_name;
00166  
00167   /* Lookup for the invalidated table in the cached tables map */
00168   QueryCacheService::CachedTablesEntries::iterator itt= QueryCacheService::cachedTables.find(key);
00169   if (itt != QueryCacheService::cachedTables.end())
00170   {
00171     /* Extract the invloved hashes from the map and lookup the local Cache*/
00172     QueryCacheService::CachedTablesEntry &entry= *itt;
00173     vector<string>::iterator hash;
00174     for(hash= entry.second.begin(); hash != entry.second.end(); hash++)
00175     {
00176       QueryCacheService::CacheEntries::iterator it= QueryCacheService::cache.find(*hash);
00177       if (it != QueryCacheService::cache.end())
00178       {
00179         /* Remove the Query from the local Cache */
00180         QueryCacheService::cache.erase(*hash);
00181         /* Remove the Query from Memcached immediatly */
00182         MemcachedQueryCache::getClient()->remove(*hash, 0);
00183       }
00184     }
00185     /* finaly remove the table from the cached table list */
00186     QueryCacheService::cachedTables.erase(key);
00187   } 
00188 }