blob: 6e2ad88f6f11db642891617045884d81e06b1808 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// 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.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*-C++-*-
*****************************************************************************
*
* File: TriggerEnable.cpp
* Description: Classes and methods used by the executor for the trigger
* enable/disable mechanism.
*
* Created: 12/30/98
* Language: C++
*
*
*
*****************************************************************************
*/
#include "TriggerEnable.h"
#include "ex_stdh.h"
#include "ComTdb.h"
#include "ex_tcb.h"
#include "ex_root.h"
#include "NAMemory.h"
//-----------------------------------------------------------------------------
//
// Accessor that guarantess tdb to tcb association
//
ComTdbRoot*
TriggerStatusWA::getRootTdb() const
{
return (ComTdbRoot*) rootTcb_->getTdb();
}
//-----------------------------------------------------------------------------
//
// Allocation and deallocation of the per-statement trigger status array.
// The private member heap_ is used.
void
TriggerStatusWA::allocateStatusArray(UInt32 numEntries)
{
if (numEntries == 0)
return;
// The following works with the VC++ compiler,
// but probably not on the NSK compiler:
// triggerStatusArray = new (heap_) TriggerStatus[numEntries];
// use our own heap_
triggerStatusArray_ =
triggerStatusArray_ =
(TriggerStatus *)new (heap_) char[numEntries * sizeof(TriggerStatus)];
// initialize the status array to all 0's
memset(triggerStatusArray_, 0, numEntries * sizeof(TriggerStatus));
currentNumEntries_ = numEntries;
}
void
TriggerStatusWA::deallocateStatusArray()
{
ex_assert(heap_, "heap of TriggerStatusArray must be initialized");
if (currentNumEntries_ == 0)
return;
currentNumEntries_ = 0;
NADELETEBASIC(triggerStatusArray_, heap_);
triggerStatusArray_ = NULL;
}
//-----------------------------------------------------------------------------
//
// Lookup of a trigger ID in the array of trigger IDs of a specific subject
// table. A lookup of a trigger that is not defined on that table returns
// TrgStatus::NOT_FOUND.
//
TriggerStatusWA::TrgStatus
TriggerStatusWA::getStatus(ComTimestamp const triggerId) const
{
ex_assert(triggerStatusArray_ != NULL, "TriggerStatusArray not initialized");
for (UInt32 i=0; i<currentNumEntries_; i++)
if (triggerStatusArray_[i].getTriggerId() == triggerId)
return (triggerStatusArray_[i].getEnableStatus() ?
ENABLED : DISABLED);
return NOT_FOUND;
}
//-----------------------------------------------------------------------------
//
// Setting an entry in the array.
//
void
TriggerStatusWA::setEntry(TriggerStatus &entry, UInt32 index)
{
ex_assert(index < currentNumEntries_,
"Out of bounds access to TriggerStatusArray");
triggerStatusArray_[index] = entry;
}
//-----------------------------------------------------------------------------
//
// Debug routine
//
#ifdef _DEBUG
void
TriggerStatusWA::print(ostream& os, const NAString& tableName)
{
os << endl << "Trigger Status Array for Table "
<< tableName << " : " << currentNumEntries_ << endl;
os << "----------------------------------------" << endl;
char int64Str[128];
for (UInt32 i=0; i<currentNumEntries_; i++)
{
convertInt64ToAscii(triggerStatusArray_[i].getTriggerId(), int64Str);
os << int64Str << " : "
<< triggerStatusArray_[i].getEnableStatus() << endl;
}
}
//-----------------------------------------------------------------------------
//
// Debug Routine
//
// displays bits in b in the following order (ignore loop variable i):
// byte_0, byte_1,...byte_l
// Within each byte:
// left to right
// MSB -> LSB
// 0,1,2,...,7
//
void bitDisplay(char * b, Int32 l)
{
UInt32 c = 0, displayMask = 1 << 7;
for (Int32 i = 0; i< l; i++)
{
memcpy(&c, b+i, 1);
for (Int32 j = 0; j < 8; j++)
{
cout << ((c & displayMask) ? '1' : '0');
c <<= 1;
}
cout << ' ';
}
cout << "\n";
}
#endif //_DEBUG
//-----------------------------------------------------------------------------
//
// For each table, this method is called and the TCB buffer holding trigger
// status is updated.
//
void
TriggerStatusWA::updateTriggerStatusPerTable()
{
Int32 triggersPerStatement = getRootTdb()->getTriggersCount();
// robustness: triggers may be dropped and disappear from rfork
// and still this method can be called from fixup phase, which
// occurs prior to similarity check.
if (getCurrentNumEntries() == 0)
return;
ex_assert(triggersPerStatement <= MAX_TRIGGERS_PER_STATEMENT,
"Too many triggers in this statement");
TrgStatus status;
unsigned char mask;
unsigned char mask2;
// first time allocation of the TCB buffer from the executor heap
if (rootTcb_->getTriggerStatusVector() == NULL)
{
char * p = new (rootTcb_->getGlobals()->getDefaultHeap())
char[TRIGGERS_STATUS_VECTOR_SIZE];
rootTcb_->setTriggerStatusVector(p);
// initialize to disabled
memset(p, 0, TRIGGERS_STATUS_VECTOR_SIZE);
}
char* tcbBuffer = rootTcb_->getTriggerStatusVector();
// for all triggers in the statement
for (Int32 i = 0; i < triggersPerStatement; i++)
{
status = getStatus(getRootTdb()->getTriggersList()[i]);
UInt32 byteOffset = i / 8;
UInt32 withinByte = i % 8;
mask = 0x80; // 128 (single 1 in MSB of byte)
mask2 = 0xFF;
switch (status)
{
// enabled
case ENABLED:
// set the appropriate bit in the mask
mask >>= withinByte;
tcbBuffer[byteOffset] |= mask;
totalTriggersCount_++;
break;
// disabled
case DISABLED:
// unset the appropriate bit in the mask
mask >>= withinByte;
mask ^= mask2;
tcbBuffer[byteOffset] &= mask;
// just count the found trigger
totalTriggersCount_++;
break;
// not found in this array of this table
case NOT_FOUND:
break;
default:
ex_assert(0, "Illegal status of a trigger");
break;
}
}
#ifdef _DEBUG
if (getenv("SHOW_ENABLE"))
{
cout << "\nTcb Buffer:\n";
bitDisplay(tcbBuffer, (getRootTdb()->getTriggersCount() / 8 + 1));
cout << endl;
}
#endif //_DEBUG
}