blob: 4ee59d6711ade877ad5bd29532be4e9c7ae07fa0 [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 @@@
// **********************************************************************
#include <Int64.h>
#include "QmsQms.h"
#include "XMLUtil.h"
#include "QRDescriptor.h"
#include "QRLogger.h"
#include "QmsInitializer.h"
/**
* \file
* Contains the main() function for the qms executable, which processes the
* input file presented as a command-line argument, or, when launched by QMM as
* a server process, enters a loop in which it waits for requests from client
* processes (either QMM or MXCMP). Requests are processed using a number of
* static, nonmember functions defined in this file, as well as classes derived
* from QRRequest.
*/
// ***************************************************************
// * performInitialization:
// *
// * Initialize the QMS process with MV Descriptor information.
// *
// * Helper routines are used to execute static SQL queries
// * to obtain all the CATALOG names known to the system.
// *
// * The individual CATALOG names are then processed to
// * obtain individual MV UIDs and MV descriptor text for
// * all MVs known to a catalog.
// ***************************************************************
QmsInitializer* QmsInitializer::instance_ = NULL;
Lng32 QmsInitializer::performInitialization()
{
// Ignore request if initialization has already been done.
if (qms_->isInitialized())
{
QRLogger::log(CAT_MEMORY, LL_WARN,
"QmsInitializer::performInitialization(): "
"Extraneous QMS initialization attempted");
return SQL_Success;
}
// start a transaction, unless one is already in progress
NABoolean startedTran = FALSE;
if (SQL_EXEC_Xact(SQLTRANS_STATUS, 0) != 0)
{
sqlInterface_.beginTransaction();
startedTran = TRUE;
}
// check if stats need to be collected - used for testing
NABoolean collectQMSStats = sqlInterface_.getCollectQMSStatsEnabled();
if (collectQMSStats)
{
collectQMSStats_ = TRUE;
// report initial heap size of QMS
logQMSStats ();
}
// Obtain all the MV descriptor text for all the MVs known for
// each CATALOG on the system.
const NAStringList* catalogNames = sqlInterface_.getAllCatalogNames();
// Process the catalogs looking for MVs
processCatalogs(catalogNames);
// Cleanup.
CollIndex maxEntries = catalogNames->entries();
for (CollIndex i=0; i<maxEntries; i++)
delete (*catalogNames)[i];
delete catalogNames;
// end the transaction, if we started it
if (startedTran)
sqlInterface_.commitTransaction();
qms_->setInitialized(TRUE);
return SQL_Success; //sqlcode_;
} // End of performInitialization
/**
* dump QMS statistics to the log
* statistics collection and logging is controlled
* by default MVQR_COLLECT_QMS_STATS
*/
void QmsInitializer::logQMSStats ()
{
Int64 totalSize = 0;
Int64 allocatedSize = 0;
NAMemory* qmsHeap = qms_->getHeap();
if (qmsHeap)
{
totalSize = qmsHeap->getTotalSize ();
allocatedSize = qmsHeap->getAllocSize ();
}
QRLogger::log(CAT_MEMORY, LL_DEBUG, "QMS total memory size: (%Ld)", totalSize);
QRLogger::log(CAT_MEMORY, LL_DEBUG, "QMS allocated memory size: (%Ld)", allocatedSize);
}
// ***************************************************************
// * processCharset
// * Obtain ISO_MAPPING and DEFAULT_CHARSET from the system
// * defaults table.
// *
// * Two helper routines are called that execute static SQL queries
// * to read the ISO_MAPPING and DEFAULT_CHARSET attribute values
// * from the system defaults table.
// ***************************************************************
void QmsInitializer::processCharset()
{
isoMapping_ = sqlInterface_.getIsoMapping();
defaultCharset_ = sqlInterface_.getDefaultCharset();
return;
} // End of processCharset
// ***************************************************************
// * Process the results of the catalog and MV searches
// ***************************************************************
void QmsInitializer::processCatalogs(const NAStringList* catalogNames)
{
if (catalogNames->isEmpty())
return;
numberOfCatalogs_ = catalogNames->entries();
for (CollIndex i=0; i < numberOfCatalogs_; i++)
{
const NAString* catalog = (*catalogNames)[i];
// Get the CAT_UID for this catalog
Int64 catalogUID = sqlInterface_.getCatalogUID(catalog);
// Get the schema definition version for this catalog
const NAString* schemaVersion = sqlInterface_.getSchemaVersion(catalogUID);
if (schemaVersion == NULL)
{
// This catalog is empty.
QRLogger::log(CAT_QMS_INIT, LL_INFO,
"Cannot get catalog Schema Version, catalog <%s> is empty",
catalog->data());
continue;
}
NAString* definitionSchema =
sqlInterface_.prepareDefinitionSchemaName(catalog, schemaVersion);
NAString textTable(*definitionSchema, heap_);
textTable += ".TEXT";
// Get all the MVs for this catalog
QRMVDefinitionList* mvDefinitions =
sqlInterface_.getMvUIDAndDefinitions(*definitionSchema);
if (!mvDefinitions->isEmpty())
{
CollIndex maxEntries = mvDefinitions->entries();
for (CollIndex j=0; j < maxEntries; j++)
{
char uid[21];
const QRMVDefinition* mvDef = (*mvDefinitions)[j];
convertInt64ToAscii(mvDef->objectUID_, uid);
// Get all the MV descriptor text buffers and attributes
// for the MVs in this specific catalog
const NAString* mvDescriptorText =
sqlInterface_.getMvDescriptor(textTable, (const char*) uid);
if (mvDescriptorText && mvDescriptorText->length())
{
// Parse and retain the MV descriptor text buffers
// and the MV attributes. Process any MV
// descriptor buffers found.
numberOfMVs_++;
processMvDescriptor(mvDef, mvDescriptorText);
delete mvDescriptorText;
}
}
// Cleanup all resources handling these descriptors
maxEntries = mvDefinitions->entries();
for (CollIndex k=0; k<maxEntries; k++)
NADELETE((*mvDefinitions)[k], QRMVDefinition, heap_);
mvDefinitions->clear();
}
delete mvDefinitions;
delete schemaVersion;
delete definitionSchema;
}
return;
} // End of processCatalogs
// ***************************************************************
// * Process the results of the MV UID and MV descriptor searches
// ***************************************************************
void QmsInitializer::processMvDescriptor(const QRMVDefinition* mvDef,
const NAString* mvDescriptorText)
{
Int32 len = 0;
try
{
QRElementMapper em;
XMLDocument doc = XMLDocument((NAHeap*)heap_, em);
XMLElementPtr mvDescriptor = NULL;
mvDescriptor = doc.parse(mvDescriptorText->data(), mvDescriptorText->length(), TRUE);
// If parsed successfully, make sure it was an MV descriptor instead of
// something else.
if (mvDescriptor->getElementType() != ET_MVDescriptor)
{
QRLogger::log(CAT_QMS_INIT, LL_WARN,
"XML document parsed ok, but had wrong document element -- %s",
mvDescriptor->getElementName());
return;
}
QRMVDescriptorPtr mvDesc = static_cast<QRMVDescriptorPtr>(mvDescriptor);
QRTablePtr mvTableName = mvDesc->getTable();
assertLogAndThrow(CAT_QMS_INIT, LL_ERROR,
mvTableName != NULL, QRLogicException,
"MV name missing from MV Descriptor.");
const NAString& mvName = mvTableName->getTableName();
// If QMS already contains this MV, drop it first, and then re-insert.
if (qms_->contains(mvName))
{
QRLogger::log(CAT_QMS_INIT, LL_INFO,
"Dropping older definition of %s before re-inserting it.",
mvName.data());
qms_->drop(mvName);
}
else
{
QRLogger::log(CAT_QMS_INIT, LL_INFO,
"Reading MV %s from SMD.", mvName.data());
}
qms_->insert(mvDesc, mvDef);
}
catch (QRException ex)
{
QRLogger::log(CAT_QMS_INIT, LL_MVQR_FAIL,
"Exception thrown processing MV Descriptor: %s. Skipping.", ex.getMessage());
}
catch (...)
{
QRLogger::log(CAT_QMS_INIT, LL_MVQR_FAIL,
"Unknown exception thrown processing MV Descriptor. Skipping.");
}
return;
} // End of processMvDescriptorTextBuffers
// ***************************************************************
// For each and ever MV defined, call catman to regenerate the
// MV descriptor.
// ***************************************************************
void QmsInitializer::reDescriber(NAString* mvName, NABoolean rePublish)
{
NABoolean result = 0;
// start a transaction
sqlInterface_.beginTransaction();
// Specific MV only
// First set the special parser flags so we can use the
// TANDEM_CAT_REQUEST syntax.
sqlInterface_.setParserFlags();
sqlInterface_.controlQueryDefault("MVQR_REWRITE_LEVEL", "1");
if (mvName)
{
QRLogger::log(CAT_QMS_INIT, LL_INFO,
"ReDescribing MV %s with rePublish %s", mvName->data(),
rePublish ? "ON" : "OFF" );
// Regenerate the descriptor.
sqlInterface_.reDescribeMV(mvName, rePublish);
}
else
{
QRLogger::log(CAT_QMS_INIT, LL_INFO,
"ReDescribing all MVs with rePublish %s", rePublish ? "ON" : "OFF" );
// Obtain all the catalog names on the system
const NAStringList* catalogNames = sqlInterface_.getAllCatalogNames();
// Collect the MV names from all the catalogs.
NAStringList mvNames(heap_);
result = collectMVNames(catalogNames, mvNames);
// Call catman to regenerate the MV descriptor for all the MVs.
if (result)
reDescribeMVs(mvNames, rePublish);
// Cleanup.
CollIndex maxEntries = catalogNames->entries();
for (CollIndex i=0; i<maxEntries; i++)
delete (*catalogNames)[i];
delete catalogNames;
}
// end the transaction
sqlInterface_.commitTransaction();
} // End of reDescriber
// ***************************************************************
// Collect the names of all the MVs in the input list of catalogs
// and add them to mvNames.
// ***************************************************************
NABoolean QmsInitializer::collectMVNames(const NAStringList* catalogNames,
NAStringList& mvNames)
{
NABoolean result = 0;
if (catalogNames->isEmpty())
return TRUE;
numberOfCatalogs_ = catalogNames->entries();
for (CollIndex i=0; i < numberOfCatalogs_; i++)
{
const NAString* catalog = (*catalogNames)[i];
// Get the CAT_UID for this catalog
Int64 catalogUID = sqlInterface_.getCatalogUID(catalog);
// Get the schema definition version for this catalog
const NAString* schemaVersion =
sqlInterface_.getSchemaVersion(catalogUID);
if (schemaVersion == NULL)
{
// This catalog is empty.
QRLogger::log(CAT_QMS_INIT, LL_INFO,
"Cannot get catalog Schema Version, catalog <%s> is empty",
catalog->data());
continue;
}
NAString* definitionSchema =
sqlInterface_.prepareDefinitionSchemaName(catalog, schemaVersion);
// Get all the MVs for this catalog
result =
sqlInterface_.collectCatalogMVs(*catalog, *definitionSchema, mvNames);
delete schemaVersion;
delete definitionSchema;
if (result == FALSE)
return FALSE;
}
return TRUE;
} // End of collectMVNames
// ***************************************************************
// For each MV in the list of MV names, call catman to regenerate
// the MV descriptor.
// ***************************************************************
void QmsInitializer::reDescribeMVs(NAStringList& mvNames, NABoolean rePublish)
{
// For each MV
for (Int32 i = (Int32)mvNames.entries()-1; i>=0; i--)
{
const NAString* mv = mvNames[i];
// Regenerate the descriptor.
sqlInterface_.reDescribeMV(mv, rePublish);
// And cleanup the memory
mvNames.remove(mv);
delete mv;
}
return;
} // End of reDescribeMVs