GError * sqlx_cache_unlock_and_close_base(sqlx_cache_t *cache, gint bd, gboolean force) { GError *err = NULL; GRID_TRACE2("%s(%p,%d,%d)", __FUNCTION__, (void*)cache, bd, force); EXTRA_ASSERT(cache != NULL); if (base_id_out(cache, bd)) return NEWERROR(CODE_INTERNAL_ERROR, "invalid base id=%d", bd); g_mutex_lock(&cache->lock); cache->used = TRUE; sqlx_base_t *base; base = GET(cache,bd); switch (base->status) { case SQLX_BASE_FREE: EXTRA_ASSERT(base->count_open == 0); EXTRA_ASSERT(base->owner == NULL); err = NEWERROR(CODE_INTERNAL_ERROR, "base not used"); break; case SQLX_BASE_IDLE: case SQLX_BASE_IDLE_HOT: EXTRA_ASSERT(base->count_open == 0); EXTRA_ASSERT(base->owner == NULL); err = NEWERROR(CODE_INTERNAL_ERROR, "base closed"); break; case SQLX_BASE_USED: EXTRA_ASSERT(base->count_open > 0); // held by the current thread if (!(-- base->count_open)) { // to be closed if (force) { _expire_base(cache, base); } else { sqlx_base_debug("CLOSING", base); base->owner = NULL; if (base->heat >= cache->heat_threshold) sqlx_base_move_to_list(cache, base, SQLX_BASE_IDLE_HOT); else sqlx_base_move_to_list(cache, base, SQLX_BASE_IDLE); } } break; case SQLX_BASE_CLOSING: EXTRA_ASSERT(base->owner != NULL); EXTRA_ASSERT(base->owner != g_thread_self()); err = NEWERROR(CODE_INTERNAL_ERROR, "base being closed"); break; } if (base && !err) sqlx_base_debug(__FUNCTION__, base); g_cond_signal(base->cond); g_mutex_unlock(&cache->lock); return err; }
static sqlx_base_t * sqlx_get_by_id(sqlx_cache_t *cache, gint i) { return base_id_out(cache, i) ? NULL : cache->bases + i; }