Exemplo n.º 1
0
CDbapiConnMgr&
CDbapiConnMgr::Instance(void)
{
    static CSafeStaticPtr<CDbapiConnMgr> instance;

    return instance.Get();
}
Exemplo n.º 2
0
const CCgiEntry& CCgiContext::GetRequestValue(const string& name,
                                              bool*         is_found)
    const
{
    pair<TCgiEntriesCI, TCgiEntriesCI> range =
        GetRequest().GetEntries().equal_range(name);

    if (range.second == range.first) {
        if ( is_found ) {
            *is_found = false;
        }
        static CSafeStaticPtr<CCgiEntry> s_EmptyCgiEntry; 
        return s_EmptyCgiEntry.Get();
    }
    if ( is_found ) {
        *is_found = true;
    }

    const CCgiEntry& value = range.first->second;
    while (++range.first != range.second) {
        if (range.first->second != value) {
            THROW1_TRACE(runtime_error,
                         "duplicate entries in request with name: " +
                         name + ": " + value.GetValue() + "!=" +
                         range.first->second.GetValue());
        }
    }
    return value;
}
Exemplo n.º 3
0
static const string& GetModuleName(const char* moduleName)
{
    CFastMutexGuard GUARD(s_ModuleNameMutex);
    static CSafeStaticPtr< set<string> > s_ModuleNames;
    const string& s = *s_ModuleNames.Get().insert(moduleName).first;
    CClassTypeInfoBase::RegisterModule(s);
    return s;
}
void CInterProcessLock::Unlock()
{
    if (m_Handle == kInvalidLockHandle) {
        NCBI_THROW(CInterProcessLockException, eNotLocked,
                   "Attempt to unlock not-yet-acquired lock");
    }
    CFastMutexGuard LOCK(s_ProcessLock);

    // Check that lock with specified name not already locked
    // in the current process.
    TLocks::iterator it = s_Locks->find(m_SystemName);
    _VERIFY(it != s_Locks->end());

    if ( it->second > 1 ) {
        // Just decrease reference counter
        it->second--;
        return;
    }

    // Release lock

#if defined(NCBI_OS_UNIX)

#  if defined(F_TLOCK)
    int res = lockf(m_Handle, F_ULOCK, 0);
#  elif defined(F_SETLK)
    struct flock lockparam;
    lockparam.l_type   = F_UNLCK;
    lockparam.l_whence = SEEK_SET;
    lockparam.l_start  = 0;
    lockparam.l_len    = 0;  /* whole file */
    int res = fcntl(m_Handle, F_SETLK, &lockparam);
#  else
#   error "No supported lock method.  Please port this code."
#  endif
    if ( res < 0 ) {
        NCBI_THROW(CInterProcessLockException, eUnlockError,
                   "Cannot release the lock");
    }
    close(m_Handle);
    
#elif defined(NCBI_OS_MSWIN)
    if ( !::ReleaseMutex(m_Handle) ) {
        NCBI_THROW(CInterProcessLockException, eUnlockError,
                   "Cannot release the lock");
    }
    ::CloseHandle(m_Handle);
#endif
    m_Handle = kInvalidLockHandle;
    s_Locks->erase(m_SystemName);
}
Exemplo n.º 5
0
// CObject local new operator to mark allocation in heap
void* CObject::operator new(size_t size)
{
    _ASSERT(size >= sizeof(CObject));
    size = max(size, sizeof(CObject) + sizeof(TCounter));

#ifdef USE_SINGLE_ALLOC
    void* ptr = single_alloc(size);
    sx_FillNewMemory(ptr, size);
    //static_cast<CObject*>(ptr)->m_Counter.Set(0);
    return ptr;
#else
    void* ptr = ::operator new(size);

#if USE_TLS_PTR
    // just remember pointer in TLS
    sx_PushLastNewPtr(ptr, eMagicCounterNew);
#else// !USE_TLS_PTR
#if USE_HEAPOBJ_LIST
    {{
        CFastMutexGuard LOCK(sm_ObjectMutex);
        s_heap_obj->push_front(ptr);
    }}
#else// !USE_HEAPOBJ_LIST
    sx_FillNewMemory(ptr, size);
#  if USE_COMPLEX_MASK
    GetSecondCounter(static_cast<CObject*>(ptr))->Set(eMagicCounterNew);
#  endif// USE_COMPLEX_MASK
#endif// USE_HEAPOBJ_LIST
    static_cast<CObject*>(ptr)->m_Counter.Set(eMagicCounterNew);
#endif// USE_TLS_PTR
    return ptr;
#endif
}
Exemplo n.º 6
0
static SServerAddress* s_GetFallbackServer()
{
    if (s_FallbackServer_Initialized)
        return s_FallbackServer->get();
    try {
        string host, port;
        if (NStr::SplitInTwo(TCGI_NetCacheFallbackServer::GetDefault(),
                ":", host, port)) {
            s_FallbackServer->reset(new SServerAddress(
                    g_NetService_gethostbyname(host),
                            (unsigned short) NStr::StringToInt(port)));
        }
    } catch (...) {
    }
    s_FallbackServer_Initialized = true;
    return s_FallbackServer->get();
}
Exemplo n.º 7
0
CValueConvert<SRunTimeSqlCP, CDB_Object>::operator const CTime&(void) const
{
    CheckNULL(m_Value);
    CheckType(m_Value, eDB_SmallDateTime, eDB_DateTime);

    EDB_Type cur_type = m_Value.GetType();
    
    if (cur_type == eDB_SmallDateTime) {
        return static_cast<const CDB_SmallDateTime&>(m_Value).Value();
    } else if (cur_type == eDB_DateTime) {
        return static_cast<const CDB_DateTime&>(m_Value).Value();
    } else {
        ReportTypeConvError(cur_type, "CTime");
    }

    static CSafeStaticPtr<CTime> value;
    return value.Get();
}
Exemplo n.º 8
0
// initialization in debug mode
inline
void CObject::InitCounter(void)
{
#if USE_TLS_PTR
    if ( CAtomicCounter::TValue type = sx_PopLastNewPtr(this) ) {
        switch ( type ) {
        case eMagicCounterNew:
            // allocated in heap
            m_Counter.Set(eInitCounterInHeap);
            break;
        case eMagicCounterPoolNew:
            // allocated in memory pool
            m_Counter.Set(eInitCounterInPool);
            break;
        default:
            ERR_POST_X(1, ObjFatal << "CObject::InitCounter: "
                       "Bad s_LastNewType="<<type<<
                       " at "<<StackTrace);
            // something is broken in TLS data
            // mark as not in heap
            m_Counter.Set(eInitCounterNotInHeap);
            break;
        }
    }
    else {
        // surely not in heap
        m_Counter.Set(eInitCounterNotInHeap);
    }
#else
    // This code can't use Get(), which may block waiting for an
    // update that will never happen.
    // ATTENTION:  this code can cause UMR (Uninit Mem Read) -- it's okay here!
    TCount main_counter = m_Counter.m_Value;
    if ( main_counter != eMagicCounterNew &&
         main_counter != eMagicCounterPoolNew ) {
        // takes care of statically allocated case
        m_Counter.Set(eInitCounterNotInHeap);
    }
    else {
        bool inStack = false;
#if USE_HEAPOBJ_LIST
        const void* ptr = dynamic_cast<const void*>(this);
        {{
            CFastMutexGuard LOCK(sm_ObjectMutex);
            list<const void*>::iterator i =
                find( s_heap_obj->begin(), s_heap_obj->end(), ptr);
            inStack = (i == s_heap_obj->end());
            if (!inStack) {
                s_heap_obj->erase(i);
            }
        }}
#else // USE_HEAPOBJ_LIST
#  if USE_COMPLEX_MASK
        inStack = GetSecondCounter(this)->m_Value != main_counter;
#  endif // USE_COMPLEX_MASK
        // m_Counter == main_counter -> possibly in heap
        if ( !inStack ) {
            char stackObject;
            const char* stackObjectPtr = &stackObject;
            const char* objectPtr = reinterpret_cast<const char*>(this);
#  if defined STACK_GROWS_UP
            inStack =
                (objectPtr < stackObjectPtr) && 
                (objectPtr > stackObjectPtr - STACK_THRESHOLD);
#  elif defined STACK_GROWS_DOWN
            inStack =
                (objectPtr > stackObjectPtr) &&
                (objectPtr < stackObjectPtr + STACK_THRESHOLD);
#  else
            inStack =
                (objectPtr < stackObjectPtr + STACK_THRESHOLD) && 
                (objectPtr > stackObjectPtr - STACK_THRESHOLD);
#  endif
        }
#endif // USE_HEAPOBJ_LIST
        
        if ( inStack ) {
            // surely not in heap
            m_Counter.Set(eInitCounterInStack);
        }
        else if ( main_counter == eMagicCounterNew ) {
            // allocated in heap
            m_Counter.Set(eInitCounterInHeap);
        }
        else {
            // allocated in memory pool
            m_Counter.Set(eInitCounterInPool);
        }
    }
#endif
}
void CInterProcessLock::Lock(const CTimeout& timeout,
                             const CTimeout& granularity)
{
    CFastMutexGuard LOCK(s_ProcessLock);

    // Check that lock with specified name not already locked
    // in the current process.
    TLocks::iterator it = s_Locks->find(m_SystemName);

    if (m_Handle != kInvalidLockHandle) {
        // The lock is already set in this CInterProcessLock object,
        // just increase reference counter.
        _VERIFY(it != s_Locks->end());
        it->second++;
        return;
    } else {
        if (it != s_Locks->end()) {
            // The lock already exists in the current process.
            // We can use one CInterProcessLock object with
            // multiple Lock() calls, but not with different
            // CInterProcessLock objects. For example, on MS-Windows,
            // we cannot wait on the same mutex in the same thread.
            // So, two different objects can set locks simultaneously.
            // And for OS-compatibility we can do nothing here,
            // except throwing an exception.
            NCBI_THROW(CInterProcessLockException, eMultipleLocks,
                       "Attempt to lock already locked object " \
                       "in the same process");
        }
    }

    // Try to acquire a lock with specified timeout

#if defined(NCBI_OS_UNIX)

    // Open lock file
    mode_t perm = CDirEntry::MakeModeT(
        CDirEntry::fRead | CDirEntry::fWrite /* user */,
        CDirEntry::fRead | CDirEntry::fWrite /* group */,
        0, 0 /* other & special */);
    int fd = open(m_SystemName.c_str(), O_CREAT | O_RDWR, perm);
    if (fd == -1) {
        NCBI_THROW(CInterProcessLockException, eCreateError,
                   string("Error creating lockfile ") + m_SystemName + 
                   ": " + strerror(errno));
    }

    // Try to acquire the lock
    
    int x_errno = 0;
    
    if (timeout.IsInfinite()  ||  timeout.IsDefault()) {
        while ((x_errno = s_UnixLock(fd))) {
            if (errno != EAGAIN)
                break;
        }

    } else {
        unsigned long ms = timeout.GetAsMilliSeconds();
        if ( !ms ) {
            // Timeout == 0
            x_errno = s_UnixLock(fd);
        } else {
            // Timeout > 0
            unsigned long ms_gran;
            if ( granularity.IsInfinite()  ||
                 granularity.IsDefault() ) 
            {
                ms_gran = min(ms/5, (unsigned long)500);
            } else {
                ms_gran = granularity.GetAsMilliSeconds();
            }
            // Try to lock within specified timeout
            for (;;) {
                x_errno = s_UnixLock(fd);
                if ( !x_errno ) {
                    // Successfully locked
                    break;
                }
                if (x_errno != EACCES  &&
                    x_errno != EAGAIN ) {
                    // Error
                    break;
                }
                // Otherwise -- sleep granularity timeout
                unsigned long ms_sleep = ms_gran;
                if (ms_sleep > ms) {
                    ms_sleep = ms;
                }
                if ( !ms_sleep ) {
                     break;
                }
                SleepMilliSec(ms_sleep);
                ms -= ms_sleep;
            }
            // Timeout
            if ( !ms ) {
                close(fd);
                NCBI_THROW(CInterProcessLockException, eLockTimeout,
                           "The lock could not be acquired in the time " \
                           "allotted");
            }
        } // if (!ms)
    } // if (timeout.IsInfinite())
    
    // Error
    if ( x_errno ) {
        close(fd);
        NCBI_THROW(CInterProcessLockException, eLockError,
                   "Error creating lock");
    }
    // Success
    m_Handle = fd;

#elif defined(NCBI_OS_MSWIN)

    HANDLE  handle  = ::CreateMutex(NULL, TRUE, _T_XCSTRING(m_SystemName));
    errno_t errcode = ::GetLastError();
    if (handle == kInvalidLockHandle) {
        switch(errcode) {
            case ERROR_ACCESS_DENIED:
                // Mutex with specified name already exists, 
                // but we don't have enough rights to open it.
                NCBI_THROW(CInterProcessLockException, eLockError,
                           "The lock already exists");
                break;
            case ERROR_INVALID_HANDLE:
                // Some system object with the same name already exists
                NCBI_THROW(CInterProcessLockException, eLockError,
                           "Error creating lock, system object with the same" \
                           "name already exists");
                break;
            default:
                // Unknown error
                NCBI_THROW(CInterProcessLockException, eCreateError,
                           "Error creating lock");
                break;
        }
    } else {
        // Mutex with specified name already exists
        if (errcode == ERROR_ALREADY_EXISTS) {
            // Wait
            DWORD res;
            if (timeout.IsInfinite()  ||  timeout.IsDefault()) {
                res = WaitForSingleObject(handle, INFINITE);
            } else {
                res = WaitForSingleObject(handle, timeout.GetAsMilliSeconds());
            }
            switch(res) {
                case WAIT_OBJECT_0:
                    // The lock has been acquired
                    break;
                case WAIT_TIMEOUT:
                    ::CloseHandle(handle);
                    NCBI_THROW(CInterProcessLockException, eLockTimeout,
                               "The lock could not be acquired in the time " \
                               "allotted");
                    break;
                case WAIT_ABANDONED:
                    // The lock is in abandoned state... Other thread/process
                    // owning it was terminated. We can reuse this mutex, but 
                    // it is better to wait until it will be released by OS.
                    /* FALLTHRU */
                default:
                    ::CloseHandle(handle);
                    NCBI_THROW(CInterProcessLockException, eLockError,
                               "Error creating lock");
                    break;
            }
        }
        m_Handle = handle;
    }
#endif
    // Set reference counter to 1
    (*s_Locks)[m_SystemName] = 1;
}