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