1 /* $Id: gbload_util.cpp 440703 2014-07-16 15:38:41Z vasilche $ 2 * =========================================================================== 3 * 4 * PUBLIC DOMAIN NOTICE 5 * National Center for Biotechnology Information 6 * 7 * This software/database is a "United States Government Work" under the 8 * terms of the United States Copyright Act. It was written as part of 9 * the author's official duties as a United States Government employee and 10 * thus cannot be copyrighted. This software/database is freely available 11 * to the public for use. The National Library of Medicine and the U.S. 12 * Government have not placed any restriction on its use or reproduction. 13 * 14 * Although all reasonable efforts have been taken to ensure the accuracy 15 * and reliability of the software and data, the NLM and the U.S. 16 * Government do not and cannot warrant the performance or results that 17 * may be obtained by using this software or data. The NLM and the U.S. 18 * Government disclaim all warranties, express or implied, including 19 * warranties of performance, merchantability or fitness for any particular 20 * purpose. 21 * 22 * Please cite the author in any work or product based on this material. 23 * 24 * =========================================================================== 25 * 26 * Author: Michael Kimelman 27 * 28 * File Description: GenBank Data loader 29 * 30 */ 31 32 #include <ncbi_pch.hpp> 33 #include <objtools/data_loaders/genbank/impl/gbload_util.hpp> 34 #include <objtools/data_loaders/genbank/gbloader.hpp> 35 #include <objtools/error_codes.hpp> 36 #include <objmgr/impl/handle_range.hpp> 37 #include <objmgr/objmgr_exception.hpp> 38 39 40 #define NCBI_USE_ERRCODE_X Objtools_GB_Util 41 42 BEGIN_NCBI_SCOPE 43 BEGIN_SCOPE(objects) 44 45 //============================================================================ 46 // Support Classes 47 // 48 49 50 /* =========================================================================== */ 51 #if 0 52 ////////////////////////////////////////////////////////////////////////////// 53 // 54 // CTimer 55 56 CTimer::CTimer(void) 57 : m_RequestsDevider(0), m_Requests(0) 58 { 59 m_ReasonableRefreshDelay = 0; 60 m_LastCalibrated = m_Time= time(0); 61 } 62 63 64 time_t CTimer::Time(void) 65 { 66 if(--m_Requests>0) 67 return m_Time; 68 m_RequestsLock.Lock(); 69 if(m_Requests<=0) { 70 time_t x = time(0); 71 if(x==m_Time) { 72 m_Requests += m_RequestsDevider + 1; 73 m_RequestsDevider = m_RequestsDevider*2 + 1; 74 } else { 75 m_Requests = m_RequestsDevider / ( x - m_Time ); 76 m_Time=x; 77 } 78 } 79 m_RequestsLock.Unlock(); 80 return m_Time; 81 } 82 83 84 void CTimer::Start(void) 85 { 86 m_TimerLock.Lock(); 87 m_StartTime = Time(); 88 } 89 90 91 void CTimer::Stop(void) 92 { 93 time_t x = Time() - m_StartTime; // test request timing in seconds 94 m_ReasonableRefreshDelay = 60 /*sec*/ * 95 (x==0 ? 5 /*min*/ : x*50 /* 50 min per sec of test request*/); 96 m_LastCalibrated = m_Time; 97 m_TimerLock.Unlock(); 98 } 99 100 101 time_t CTimer::RetryTime(void) 102 { 103 return Time() + 104 (m_ReasonableRefreshDelay>0?m_ReasonableRefreshDelay:24*60*60); 105 /* 24 hours */ 106 } 107 108 109 bool CTimer::NeedCalibration(void) 110 { 111 return 112 (m_ReasonableRefreshDelay==0) || 113 (m_Time-m_LastCalibrated>100*m_ReasonableRefreshDelay); 114 } 115 #endif 116 117 #if 0 118 void CRefresher::Reset(CTimer &timer) 119 { 120 m_RefreshTime = timer.RetryTime(); 121 } 122 123 124 bool CRefresher::NeedRefresh(CTimer &timer) const 125 { 126 return timer.Time() > m_RefreshTime; 127 } 128 129 130 // MutexPool 131 // 132 133 #if defined(NCBI_THREADS) 134 CMutexPool::CMutexPool() 135 { 136 m_size =0; 137 m_Locks=0; 138 spread =0; 139 } 140 141 142 void CMutexPool::SetSize(int size) 143 { 144 _VERIFY(m_size==0 && !m_Locks); 145 m_size = size; 146 m_Locks = new CMutex[m_size]; 147 spread = new int[m_size]; 148 for ( int i = 0; i < m_size; ++i ) { 149 spread[i]=0; 150 } 151 } 152 153 154 CMutexPool::~CMutexPool(void) 155 { 156 delete [] m_Locks; 157 if ( spread ) { 158 for ( int i = 0; i < m_size; ++i ) { 159 GBLOG_POST_X(1, "PoolMutex " << i << " used "<< spread[i] << " times"); 160 } 161 } 162 delete [] spread; 163 } 164 #else 165 CMutex CMutexPool::sm_Lock; 166 #endif 167 168 /* =========================================================================== */ 169 // CGBLGuard 170 // 171 CGBLGuard::CGBLGuard(TLMutex& lm,EState orig,const char *loc,int select) 172 : m_Locks(&lm), 173 m_Loc(loc), 174 m_orig(orig), 175 m_current(orig), 176 m_select(select) 177 { 178 } 179 180 CGBLGuard::CGBLGuard(TLMutex &lm,const char *loc) 181 // assume orig=eNone, switch to e.Main in constructor 182 : m_Locks(&lm), 183 m_Loc(loc), 184 m_orig(eNone), 185 m_current(eNone), 186 m_select(-1) 187 { 188 Switch(eMain); 189 } 190 191 CGBLGuard::CGBLGuard(CGBLGuard &g,const char *loc) 192 : m_Locks(g.m_Locks), 193 m_Loc(g.m_Loc), 194 m_orig(g.m_current), 195 m_current(g.m_current), 196 m_select(g.m_select) 197 { 198 if ( loc ) { 199 m_Loc = loc; 200 } 201 _VERIFY(m_Locks); 202 } 203 204 CGBLGuard::~CGBLGuard() 205 { 206 Switch(m_orig); 207 } 208 209 #if defined(NCBI_THREADS) 210 void CGBLGuard::Select(int s) 211 { 212 if ( m_current==eMain ) { 213 m_select=s; 214 } 215 _ASSERT(m_select==s); 216 } 217 218 #define LOCK_POST(err_subcode, x) GBLOG_POST_X(err_subcode, x) 219 //#define LOCK_POST(err_subcode, x) 220 void CGBLGuard::MLock() 221 { 222 LOCK_POST(2, &m_Locks << ":: MainLock tried @ " << m_Loc); 223 m_Locks->m_Lookup.Lock(); 224 LOCK_POST(3, &m_Locks << ":: MainLock locked @ " << m_Loc); 225 } 226 227 void CGBLGuard::MUnlock() 228 { 229 LOCK_POST(4, &m_Locks << ":: MainLock unlocked@ " << m_Loc); 230 m_Locks->m_Lookup.Unlock(); 231 } 232 233 void CGBLGuard::PLock() 234 { 235 _ASSERT(m_select>=0); 236 LOCK_POST(5, &m_Locks << ":: Pool["<< setw(2) << m_select << "] tried @ " 237 << m_Loc); 238 m_Locks->m_Pool.GetMutex(m_select).Lock(); 239 LOCK_POST(6, &m_Locks << ":: Pool["<< setw(2) << m_select << "] locked @ " 240 << m_Loc); 241 } 242 243 void CGBLGuard::PUnlock() 244 { 245 _ASSERT(m_select>=0); 246 LOCK_POST(7, &m_Locks << ":: Pool["<< setw(2) << m_select << "] unlocked@ " 247 << m_Loc); 248 m_Locks->m_Pool.GetMutex(m_select).Unlock(); 249 } 250 251 void CGBLGuard::Switch(EState newstate) 252 { 253 if(newstate==m_current) return; 254 switch(newstate) { 255 case eNone: 256 if ( m_current!=eMain ) { 257 Switch(eMain); 258 } 259 _ASSERT(m_current==eMain); 260 //LOCK_POST(8, &m_Locks << ":: switch 'main' to 'none'"); 261 MUnlock(); 262 m_current=eNone; 263 return; 264 265 case eBoth: 266 if ( m_current!=eMain ) { 267 Switch(eMain); 268 } 269 _ASSERT(m_current==eMain); 270 //LOCK_POST(9, &m_Locks << ":: switch 'main' to 'both'"); 271 if ( m_Locks->m_SlowTraverseMode>0 ) { 272 PLock(); 273 } 274 m_current=eBoth; 275 return; 276 277 case eLocal: 278 if ( m_current!=eBoth ) { 279 Switch(eBoth); 280 } 281 _ASSERT(m_current==eBoth); 282 //LOCK_POST(10, &m_Locks << ":: switch 'both' to 'local'"); 283 if(m_Locks->m_SlowTraverseMode==0) { 284 PLock(); 285 } 286 try { 287 m_Locks->m_SlowTraverseMode++; 288 MUnlock(); 289 } 290 catch( exception& ) { 291 m_Locks->m_SlowTraverseMode--; 292 if(m_Locks->m_SlowTraverseMode==0) { 293 PUnlock(); 294 } 295 throw; 296 } 297 m_current=eLocal; 298 return; 299 case eMain: 300 switch(m_current) { 301 case eNone: 302 m_select=-1; 303 //LOCK_POST(11, &m_Locks << ":: switch 'none' to 'main'"); 304 MLock(); 305 m_current=eMain; 306 return; 307 case eBoth: 308 //LOCK_POST(12, &m_Locks << ":: switch 'both' to 'main'"); 309 if(m_Locks->m_SlowTraverseMode>0) { 310 PUnlock(); 311 } 312 m_select=-1; 313 m_current=eMain; 314 return; 315 case eLocal: 316 //LOCK_POST(13, &m_Locks << ":: switch 'local' to 'none2main'"); 317 PUnlock(); 318 m_current=eNoneToMain; 319 case eNoneToMain: 320 //LOCK_POST(14, &m_Locks << ":: switch 'none2main' to 'main'"); 321 MLock(); 322 m_Locks->m_SlowTraverseMode--; 323 m_select=-1; 324 m_current=eMain; 325 return; 326 default: 327 break; 328 } 329 default: 330 break; 331 } 332 NCBI_THROW(CLoaderException, eOtherError, 333 "CGBLGuard::Switch - state desynchronized"); 334 } 335 #endif // if(NCBI_THREADS) 336 337 #endif 338 339 END_SCOPE(objects) 340 END_NCBI_SCOPE 341