blob: 3922b4ba87abb39a24a497d3c96fcfb14be163c4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "resqueuedeadlock.h"
#include "dynrm.h"
#include "utils/simplestring.h"
#include "resqueuemanager.h"
void initializeResqueueDeadLockDetector(ResqueueDeadLockDetector detector,
void *queuetrack)
{
Assert( detector != NULL );
detector->ResqueueTrack = (DynResourceQueueTrack)queuetrack;
initializeHASHTABLE(&(detector->Sessions),
PCONTEXT,
HASHTABLE_SLOT_VOLUME_DEFAULT,
HASHTABLE_SLOT_VOLUME_DEFAULT_MAX,
HASHTABLE_KEYTYPE_CHARARRAY,
NULL);
resetResourceBundleData(&(detector->InUseTotal), 0, 0.0, 0);
resetResourceBundleData(&(detector->LockedTotal), 0, 0.0, 0);
}
int addSessionInUseResource(ResqueueDeadLockDetector detector,
int64_t sessionid,
uint32_t memorymb,
double core)
{
/* Build key */
SimpArray key;
setSimpleArrayRef(&key, (char *)&sessionid, sizeof(int64_t));
/* Check if the session id exists. */
PAIR pair = getHASHTABLENode(&(detector->Sessions), &key);
if ( pair == NULL ) {
return RESQUEMGR_NO_SESSIONID;
}
SessionTrack sessiontrack = (SessionTrack)(pair->Value);
Assert( sessiontrack != NULL );
Assert( !sessiontrack->Locked );
addResourceBundleData(&(sessiontrack->InUseTotal), memorymb, core);
addResourceBundleData(&(detector->InUseTotal), memorymb, core);
elog(DEBUG3, "Deadlock detector adds in-use %d MB from session "INT64_FORMAT", "
"has %d MB in use %d MB locked.",
memorymb,
sessionid,
detector->InUseTotal.MemoryMB,
detector->LockedTotal.MemoryMB);
return FUNC_RETURN_OK;
}
int minusSessionInUseResource(ResqueueDeadLockDetector detector,
int64_t sessionid,
uint32_t memorymb,
double core)
{
/* Build key */
SimpArray key;
setSimpleArrayRef(&key, (char *)&sessionid, sizeof(int64_t));
/* Check if the session id exists. */
PAIR pair = getHASHTABLENode(&(detector->Sessions), &key);
if ( pair == NULL ) {
return RESQUEMGR_NO_SESSIONID;
}
minusResourceBundleData(&(detector->InUseTotal), memorymb, core);
SessionTrack sessiontrack = (SessionTrack)(pair->Value);
Assert( sessiontrack != NULL );
minusResourceBundleData(&(sessiontrack->InUseTotal), memorymb, core);
Assert(detector->InUseTotal.Core >= 0.0 &&
detector->InUseTotal.MemoryMB >= 0);
Assert(sessiontrack->InUseTotal.Core >= 0.0 &&
sessiontrack->InUseTotal.MemoryMB >= 0);
/* If the session has no resource used, remove the session tracker. */
if ( sessiontrack->InUseTotal.MemoryMB == 0 &&
sessiontrack->InUseTotal.Core == 0.0 )
{
rm_pfree(PCONTEXT, sessiontrack);
removeHASHTABLENode(&(detector->Sessions), &key);
}
elog(DEBUG3, "Deadlock detector reduces in-use %d MB from session "INT64_FORMAT", "
"has %d MB in use %d MB locked.",
memorymb,
sessionid,
detector->InUseTotal.MemoryMB,
detector->LockedTotal.MemoryMB);
return FUNC_RETURN_OK;
}
void createAndLockSessionResource(ResqueueDeadLockDetector detector,
int64_t sessionid)
{
SessionTrack curstrack = NULL;
/* Build key */
SimpArray key;
setSimpleArrayRef(&key, (char *)&sessionid, sizeof(int64_t));
/* Check if the session id exists. */
PAIR pair = getHASHTABLENode(&(detector->Sessions), &key);
if ( pair == NULL )
{
curstrack = (SessionTrack)rm_palloc0(PCONTEXT, sizeof(SessionTrackData));
curstrack->SessionID = sessionid;
curstrack->Locked = false;
resetResourceBundleData(&(curstrack->InUseTotal), 0, 0.0, 0);
/* Add to the detector. */
setHASHTABLENode(&(detector->Sessions), &key, curstrack, false);
}
else
{
curstrack = (SessionTrack)(pair->Value);
}
Assert( curstrack != NULL );
Assert( !curstrack->Locked );
curstrack->Locked = true;
addResourceBundleDataByBundle(&(detector->LockedTotal),
&(curstrack->InUseTotal));
elog(DEBUG3, "Deadlock detector locked session "INT64_FORMAT
", has %d MB in use %d MB locked",
sessionid,
detector->InUseTotal.MemoryMB,
detector->LockedTotal.MemoryMB);
}
void unlockSessionResource(ResqueueDeadLockDetector detector,
int64_t sessionid)
{
/* Build key */
SimpArray key;
setSimpleArrayRef(&key, (char *)&sessionid, sizeof(int64_t));
/* Check if the session id exists. */
PAIR pair = getHASHTABLENode(&(detector->Sessions), &key);
if ( pair != NULL )
{
SessionTrack sessiontrack = (SessionTrack)(pair->Value);
Assert(sessiontrack != NULL);
Assert(sessiontrack->Locked);
minusResourceBundleDataByBundle(&(detector->LockedTotal),
&(sessiontrack->InUseTotal));
sessiontrack->Locked = false;
elog(DEBUG3, "Deadlock detector unlocked session "INT64_FORMAT
", has %d MB in use %d MB locked",
sessionid,
detector->InUseTotal.MemoryMB,
detector->LockedTotal.MemoryMB);
}
Assert(detector->LockedTotal.Core >= 0.0 &&
detector->LockedTotal.MemoryMB >= 0);
}
SessionTrack findSession(ResqueueDeadLockDetector detector,
int64_t sessionid)
{
/* Build key */
SimpArray key;
setSimpleArrayRef(&key, (char *)&sessionid, sizeof(int64_t));
/* Check if the session id exists. */
PAIR pair = getHASHTABLENode(&(detector->Sessions), &key);
if ( pair != NULL )
{
return (SessionTrack)(pair->Value);
}
return NULL;
}
void resetResourceDeadLockDetector(ResqueueDeadLockDetector detector)
{
List *allss = NULL;
ListCell *cell = NULL;
getAllPAIRRefIntoList(&(detector->Sessions), &allss);
foreach(cell, allss)
{
SessionTrack strack = (SessionTrack)(((PAIR)lfirst(cell))->Value);
rm_pfree(PCONTEXT, strack);
}
freePAIRRefList(&(PCONTRACK->Connections), &allss);
clearHASHTABLE(&(detector->Sessions));
resetResourceBundleData(&(detector->InUseTotal), 0, 0.0, 0);
resetResourceBundleData(&(detector->LockedTotal), 0, 0.0, 0);
}
void copyResourceDeadLockDetectorWithoutLocking(ResqueueDeadLockDetector source,
ResqueueDeadLockDetector target)
{
Assert(source != NULL);
Assert(target != NULL);
resetResourceDeadLockDetector(target);
target->ResqueueTrack = source->ResqueueTrack;
addResourceBundleDataByBundle(&(target->InUseTotal), &(source->InUseTotal));
List *allss = NULL;
ListCell *cell = NULL;
getAllPAIRRefIntoList(&(source->Sessions), &allss);
foreach(cell, allss)
{
SessionTrack strack = (SessionTrack)(((PAIR)lfirst(cell))->Value);
SessionTrack newstrack = rm_palloc0(PCONTEXT, sizeof(SessionTrackData));
newstrack->SessionID = strack->SessionID;
newstrack->Locked = false;
resetResourceBundleDataByBundle(&(newstrack->InUseTotal),
&(strack->InUseTotal));
/* Add to the detector. */
SimpArray key;
setSimpleArrayRef(&key, (char *)&(newstrack->SessionID), sizeof(int64_t));
setHASHTABLENode(&(target->Sessions), &key, newstrack, false);
}
}