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 #include <drizzled/table/cache.h>
00023
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <fcntl.h>
00027
00028 #include <drizzled/identifier.h>
00029 #include <drizzled/open_tables_state.h>
00030 #include <drizzled/pthread_globals.h>
00031 #include <drizzled/session.h>
00032 #include <drizzled/sql_base.h>
00033 #include <drizzled/sys_var.h>
00034 #include <drizzled/table.h>
00035 #include <drizzled/table/concurrent.h>
00036 #include <drizzled/table/unused.h>
00037
00038 namespace drizzled {
00039 namespace table {
00040
00041 CacheMap Cache::cache;
00042 boost::mutex Cache::_mutex;
00043
00044 CacheMap& getCache()
00045 {
00046 return Cache::getCache();
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 static void free_cache_entry(table::Concurrent *table)
00061 {
00062 table->intern_close_table();
00063 if (not table->in_use)
00064 {
00065 getUnused().unlink(table);
00066 }
00067
00068 boost::checked_delete(table);
00069 }
00070
00071 void remove_table(table::Concurrent *arg)
00072 {
00073 CacheRange ppp;
00074 ppp= getCache().equal_range(arg->getShare()->getCacheKey());
00075
00076 for (CacheMap::const_iterator iter= ppp.first;
00077 iter != ppp.second; ++iter)
00078 {
00079 table::Concurrent *found_table= iter->second;
00080
00081 if (found_table == arg)
00082 {
00083 free_cache_entry(arg);
00084 getCache().erase(iter);
00085 return;
00086 }
00087 }
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 bool Cache::areTablesUsed(Table *table, bool wait_for_name_lock)
00097 {
00098 do
00099 {
00100 const identifier::Table::Key &key(table->getShare()->getCacheKey());
00101
00102 table::CacheRange ppp= table::getCache().equal_range(key);
00103
00104 for (table::CacheMap::const_iterator iter= ppp.first; iter != ppp.second; ++iter)
00105 {
00106 Table *search= iter->second;
00107 if (search->in_use == table->in_use)
00108 continue;
00109
00110
00111
00112
00113
00114
00115
00116 if ( (search->locked_by_name && wait_for_name_lock) ||
00117 (search->is_name_opened() && search->needs_reopen_or_name_lock()))
00118 return 1;
00119 }
00120 } while ((table=table->getNext()));
00121 return 0;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 void Cache::removeSchema(const identifier::Schema &schema_identifier)
00138 {
00139 boost::mutex::scoped_lock scopedLock(_mutex);
00140
00141 for (table::CacheMap::const_iterator iter= table::getCache().begin();
00142 iter != table::getCache().end();
00143 iter++)
00144 {
00145 table::Concurrent *table= iter->second;
00146
00147 if (not schema_identifier.getPath().compare(table->getShare()->getSchemaName()))
00148 {
00149 table->getMutableShare()->resetVersion();
00150 if (not table->in_use)
00151 table::getUnused().relink(table);
00152 }
00153 }
00154
00155 table::getUnused().cullByVersion();
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 bool Cache::removeTable(Session& session, const identifier::Table &identifier, uint32_t flags)
00174 {
00175 const identifier::Table::Key &key(identifier.getKey());
00176 bool result= false;
00177 bool signalled= false;
00178
00179 for (;;)
00180 {
00181 result= signalled= false;
00182
00183 table::CacheRange ppp;
00184 ppp= table::getCache().equal_range(key);
00185
00186 for (table::CacheMap::const_iterator iter= ppp.first;
00187 iter != ppp.second; ++iter)
00188 {
00189 table::Concurrent *table= iter->second;
00190 Session *in_use;
00191
00192 table->getMutableShare()->resetVersion();
00193 if (not (in_use= table->in_use))
00194 {
00195 table::getUnused().relink(table);
00196 }
00197 else if (in_use != &session)
00198 {
00199
00200
00201
00202
00203
00204 if (table->is_name_opened())
00205 {
00206 result= true;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 for (Table *session_table= in_use->open_tables.open_tables_;
00218 session_table ;
00219 session_table= session_table->getNext())
00220 {
00221
00222 if (session_table->db_stat)
00223 signalled|= session.abortLockForThread(session_table);
00224 }
00225 }
00226 else
00227 {
00228 result= result || (flags & RTFC_OWNED_BY_Session_FLAG);
00229 }
00230 }
00231
00232 table::getUnused().cullByVersion();
00233
00234
00235 table::instance::release(identifier);
00236
00237 if (result && (flags & RTFC_WAIT_OTHER_THREAD_FLAG))
00238 {
00239
00240
00241
00242
00243 locking::broadcast_refresh();
00244 if (not (flags & RTFC_CHECK_KILLED_FLAG) || not session.getKilled())
00245 {
00246 dropping_tables++;
00247 if (likely(signalled))
00248 {
00249 boost::mutex::scoped_lock scoped(table::Cache::mutex(), boost::adopt_lock_t());
00250 COND_refresh.wait(scoped);
00251 scoped.release();
00252 }
00253 else
00254 {
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 boost::xtime xt;
00266 xtime_get(&xt, boost::TIME_UTC);
00267 xt.sec += 10;
00268 boost::mutex::scoped_lock scoped(table::Cache::mutex(), boost::adopt_lock_t());
00269 COND_refresh.timed_wait(scoped, xt);
00270 scoped.release();
00271 }
00272 dropping_tables--;
00273 continue;
00274 }
00275 }
00276 break;
00277 }
00278
00279 return result;
00280 }
00281
00282
00283 void Cache::insert(table::Concurrent* arg)
00284 {
00285 CacheMap::iterator returnable= cache.insert(std::make_pair(arg->getShare()->getCacheKey(), arg));
00286 assert(returnable != cache.end());
00287 }
00288
00289 }
00290 }