/* * Copyright (c) 2019 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the GNU Affero General Public License, version 3 * or later ("AGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #define _DEFAULT_SOURCE #include "os.h" #include "taos.h" #include "tglobal.h" #include "tcache.h" #include "httpInt.h" #include "httpContext.h" #include "httpSession.h" void httpCreateSession(HttpContext *pContext, void *taos) { HttpServer *server = &tsHttpServer; httpReleaseSession(pContext); pthread_mutex_lock(&server->serverMutex); HttpSession session; memset(&session, 0, sizeof(HttpSession)); session.taos = taos; session.refCount = 1; int32_t len = snprintf(session.id, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); pContext->session = taosCachePut(server->sessionCache, session.id, len, &session, sizeof(HttpSession), tsHttpSessionExpire); // void *temp = pContext->session; // taosCacheRelease(server->sessionCache, (void **)&temp, false); if (pContext->session == NULL) { httpError("context:%p, fd:%d, ip:%s, user:%s, error:%s", pContext, pContext->fd, pContext->ipstr, pContext->user, httpMsg[HTTP_SESSION_FULL]); taos_close(taos); pthread_mutex_unlock(&server->serverMutex); return; } httpDebug("context:%p, fd:%d, ip:%s, user:%s, create a new session:%p:%p sessionRef:%d", pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); pthread_mutex_unlock(&server->serverMutex); } static void httpFetchSessionImp(HttpContext *pContext) { HttpServer *server = &tsHttpServer; pthread_mutex_lock(&server->serverMutex); char sessionId[HTTP_SESSION_ID_LEN]; int32_t len = snprintf(sessionId, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); pContext->session = taosCacheAcquireByKey(server->sessionCache, sessionId, len); if (pContext->session != NULL) { atomic_add_fetch_32(&pContext->session->refCount, 1); httpDebug("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, sessionRef:%d", pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); } else { httpDebug("context:%p, fd:%d, ip:%s, user:%s, session not found", pContext, pContext->fd, pContext->ipstr, pContext->user); } pthread_mutex_unlock(&server->serverMutex); } void httpGetSession(HttpContext *pContext) { if (pContext->session == NULL) { httpFetchSessionImp(pContext); } else { char sessionId[HTTP_SESSION_ID_LEN]; snprintf(sessionId, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); httpReleaseSession(pContext); httpFetchSessionImp(pContext); } } void httpReleaseSession(HttpContext *pContext) { if (pContext == NULL || pContext->session == NULL) return; int32_t refCount = atomic_sub_fetch_32(&pContext->session->refCount, 1); assert(refCount >= 0); httpDebug("context:%p, release session:%p:%p, sessionRef:%d", pContext, pContext->session, pContext->session->taos, pContext->session->refCount); taosCacheRelease(tsHttpServer.sessionCache, (void **)&pContext->session, false); pContext->session = NULL; } static void httpDestroySession(void *data) { HttpSession *session = data; httpDebug("session:%p:%p, is destroyed, sessionRef:%d", session, session->taos, session->refCount); if (session->taos != NULL) { taos_close(session->taos); session->taos = NULL; } } void httpCleanUpSessions() { if (tsHttpServer.sessionCache != NULL) { SCacheObj *cache = tsHttpServer.sessionCache; httpInfo("session cache is cleanuping, size:%zu", taosHashGetSize(cache->pHashTable)); taosCacheCleanup(tsHttpServer.sessionCache); tsHttpServer.sessionCache = NULL; } } bool httpInitSessions() { tsHttpServer.sessionCache = taosCacheInit(TSDB_DATA_TYPE_BINARY, 5, false, httpDestroySession, "rests"); if (tsHttpServer.sessionCache == NULL) { httpError("failed to init session cache"); return false; } return true; }