Drizzled Public API Documentation

locks.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 #include <plugin/user_locks/module.h>
00023 
00024 #include <boost/thread/locks.hpp>
00025 
00026 #include <string>
00027 
00028 namespace user_locks {
00029 
00030 bool Locks::lock(drizzled::session_id_t id_arg, const user_locks::Key &arg, int64_t wait_for)
00031 {
00032   boost::unique_lock<boost::mutex> scope(mutex);
00033   boost::system_time timeout= boost::get_system_time() + boost::posix_time::seconds(wait_for);
00034   
00035   LockMap::iterator iter;
00036   while ((iter= lock_map.find(arg)) != lock_map.end())
00037   {
00038     if (id_arg == iter->second->id)
00039     {
00040       // We own the lock, so we just exit.
00041       return true;
00042     }
00043     try {
00044       if (wait_for)
00045       {
00046         bool success= release_cond.timed_wait(scope, timeout);
00047 
00048         if (not success)
00049           return false;
00050       }
00051       else
00052       {
00053         release_cond.wait(scope);
00054       }
00055     }
00056     catch(boost::thread_interrupted const& error)
00057     {
00058       // Currently nothing is done here.
00059       throw error;
00060     }
00061   }
00062 
00063   if (iter == lock_map.end())
00064   {
00065     create_cond.notify_all();
00066     return lock_map.insert(std::make_pair(arg, new Lock(id_arg))).second;
00067   }
00068 
00069   return false;
00070 }
00071 
00072 // Currently we just let timeouts occur, and the caller will need to know
00073 // what it is looking for/whether to go back into this.
00074 void Locks::waitCreate(int64_t wait_for)
00075 {
00076   boost::unique_lock<boost::mutex> scope(mutex);
00077   boost::system_time timeout= boost::get_system_time() + boost::posix_time::seconds(wait_for);
00078 
00079   try {
00080     create_cond.timed_wait(scope, timeout);
00081   }
00082   catch(boost::thread_interrupted const& error)
00083   {
00084     // Currently nothing is done here.
00085     throw error;
00086   }
00087 }
00088 
00089 bool Locks::lock(drizzled::session_id_t id_arg, const user_locks::Keys &arg)
00090 {
00091   boost::unique_lock<boost::mutex> scope(mutex);
00092   user_locks::Keys created;
00093   bool error= false;
00094 
00095   for (user_locks::Keys::const_iterator iter= arg.begin(); iter != arg.end(); iter++)
00096   {
00097     LockMap::iterator record= lock_map.find(*iter);
00098 
00099     if (record != lock_map.end()) // Found, so check ownership of the lock
00100     {
00101       if (id_arg != (*record).second->id)
00102       {
00103         // So it turns out the locks exist, and we can't grab them all
00104         error= true;
00105         break;
00106       }
00107     }
00108     else
00109     {
00110       lock_map.insert(std::make_pair(*iter, new Lock(id_arg)));
00111       created.insert(*iter);
00112     }
00113   }
00114 
00115   if (error)
00116   {
00117     for (user_locks::Keys::const_iterator iter= created.begin(); iter != created.end(); iter++)
00118     {
00119       lock_map.erase(*iter);
00120     }
00121 
00122     return false;
00123   }
00124 
00125   create_cond.notify_all();
00126 
00127   return true;
00128 }
00129 
00130 bool Locks::isUsed(const user_locks::Key &arg, drizzled::session_id_t &id_arg)
00131 {
00132   boost::unique_lock<boost::mutex> scope(mutex);
00133   
00134   LockMap::iterator iter= lock_map.find(arg);
00135   
00136   if ( iter == lock_map.end())
00137     return false;
00138 
00139   id_arg= iter->second->id;
00140 
00141   return true;
00142 }
00143 
00144 bool Locks::isFree(const user_locks::Key &arg)
00145 {
00146   boost::unique_lock<boost::mutex> scope(mutex);
00147 
00148   LockMap::iterator iter= lock_map.find(arg);
00149   
00150   return iter != lock_map.end();
00151 }
00152 
00153 void Locks::Copy(LockMap &lock_map_arg)
00154 {
00155   boost::unique_lock<boost::mutex> scope(mutex);
00156   lock_map_arg= lock_map;
00157 }
00158 
00159 locks::return_t Locks::release(const user_locks::Key &arg, drizzled::session_id_t &id_arg, bool and_wait)
00160 {
00161   size_t elements= 0;
00162   boost::unique_lock<boost::mutex> scope(mutex);
00163   LockMap::iterator iter= lock_map.find(arg);
00164 
00165   // Nothing is found
00166   if ( iter == lock_map.end())
00167     return locks::NOT_FOUND;
00168 
00169   if (iter->second->id == id_arg)
00170   {
00171     elements= lock_map.erase(arg);
00172     assert(elements); // If we can't find what we just found, then we are broken
00173 
00174     if (elements)
00175     {
00176       release_cond.notify_one();
00177 
00178       if (and_wait)
00179       {
00180         bool found= false;
00181         while (not found)
00182         {
00183           assert(boost::this_thread::interruption_enabled());
00184           try {
00185             create_cond.wait(scope);
00186           }
00187           catch(boost::thread_interrupted const& error)
00188           {
00189             // Currently nothing is done here.
00190             throw error;
00191           }
00192           iter= lock_map.find(arg);
00193 
00194           if (iter != lock_map.end())
00195             found= true;
00196         }
00197       }
00198 
00199       return locks::SUCCESS;
00200     }
00201   }
00202 
00203   return locks::NOT_OWNED_BY;
00204 }
00205 
00206 } /* namespace user_locks */