blob: f3c67fab3c8bcfa1d5b8adfc81a58f13cbc7adfa [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 <typeinfo>
#include "TCBTreeView.h"
#include "ExeSchedWindow.h"
#include "ExeQueueDisplay.h"
#include "ui_TCBTreeView.h"
#include "CommonSqlCmpDbg.h"
#include "ComTdb.h"
#include "ex_tcb.h"
#include "ExScheduler.h"
TCBTreeView::TCBTreeView(ExeSchedWindow *mainExeWindow,
QWidget *parent) :
QWidget(parent),
ui(new Ui::TCBTreeView),
mainExeWindow_(mainExeWindow)
{
currTcb_ = NULL;
ui->setupUi(this);
QStringList header;
header << "TCB/Task Tree" << "Break" << "Scheduled" << "Down" << "Up";
QTreeWidgetItem *hdrItem = new QTreeWidgetItem(header);
hdrItem->setIcon(0, QIcon(":/file/Resource/Main/Sqlnode.bmp"));
ui->treeWidget->setHeaderItem(hdrItem);
ui->treeWidget->setSelectionBehavior(QAbstractItemView::SelectItems);
ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
ui->treeWidget->setIconSize(QSize(32, 32));
ui->treeWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
ui->treeWidget->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
}
TCBTreeView::~TCBTreeView()
{
delete ui;
}
void TCBTreeView::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
{
QVariant itemData = item->data(0, Qt::UserRole);
TcbTreeDetails *itemDetails = itemData.value <TcbTreeDetails *>();
switch (column)
{
case 0:
if (itemDetails->currTask)
{
// clicking on a task name:
// set the next task to be executed to this one
ExSubtask **subtaskPtr = mainExeWindow_->getSubtaskPtr();
if (subtaskPtr && *subtaskPtr)
*subtaskPtr = itemDetails->currTask;
}
break;
case 1:
if (itemDetails->currTask)
{
// clicking on a breakpoint cell of a task:
// toggle the breakpoint between on/off
int brkpt = itemDetails->currTask->getBreakPoint();
if (brkpt)
brkpt = 0;
else
brkpt = 1;
itemDetails->currTask->setBreakPoint(brkpt);
}
break;
case 2:
if (itemDetails->currTask)
// clicking on the "scheduled" field of a task: schedule
itemDetails->currTask->schedule();
break;
case 3:
if (itemDetails->currTask == NULL)
{
// clicking on the number of rows in the down queue:
if (!itemDetails->currDnQueueDisplay)
{
itemDetails->currDnQueueDisplay = new ExeQueueDisplay(
itemDetails->currTcb,
false,
this);
itemDetails->currDnQueueDisplay->show();
}
}
break;
case 4:
if (itemDetails->currTask == NULL)
{
// clicking on the number of rows in the up queue:
if (!itemDetails->currUpQueueDisplay)
{
itemDetails->currUpQueueDisplay = new ExeQueueDisplay(
itemDetails->currTcb,
true,
this);
itemDetails->currUpQueueDisplay->show();
}
}
break;
default:
break;
}
if (itemDetails->currTask)
setBreakSchedInfo(item,
(itemDetails->currTask->getBreakPoint() > 0 ? 1 : 0),
(itemDetails->currTask->isScheduled() ? "*" : ""));
}
void TCBTreeView::UpdateView()
{
//------------------------------------------------------------------
// Delete the existing Tree.
//------------------------------------------------------------------
}
void TCBTreeView::displayTcbTree(const ex_tcb *tcb,
ExSubtask *currSubtask,
ExScheduler *sched,
bool includeTasks,
QTreeWidgetItem * parentTreeItem)
{
if (parentTreeItem == NULL)
{
// for the top-level caller, start with the fragment root TCB
currTcb_ = tcb;
tcb = sched->getLocalRootTcbForGui();
}
if (tcb != NULL)
{
const ComTdb *tdb = tcb->getTdb();
int arity = tcb->numChildren();
Int32 bitmapIndex;
QString nodeText;
const char *breakText = " ";
const char *scheduledText = " ";
TcbTreeDetails *itemDetails = new TcbTreeDetails(tcb, sched);
getOperatorImageText(tdb, bitmapIndex, nodeText);
QStringList rowValues;
ex_queue_pair parentQueue = tcb->getParentQueue();
rowValues.append(nodeText);
QTreeWidgetItem *tcbTreeItem = new QTreeWidgetItem(rowValues);
if (parentQueue.down)
{
tcbTreeItem->setText(3, QString("%1").arg(parentQueue.down->getLength()));
if (parentQueue.down->isFull())
tcbTreeItem->setBackgroundColor(3, QColor("mistyrose"));
}
if (parentQueue.up)
{
tcbTreeItem->setText(4, QString("%1").arg(parentQueue.up->getLength()));
if (parentQueue.up->isFull())
tcbTreeItem->setBackgroundColor(4, QColor("mistyrose"));
}
tcbTreeItem->setIcon(0, QIcon(":/file/Resource/Main/Sqlnode.bmp"));
QString tip = QString("%1@0x%2").arg(typeid(*tcb).name()).arg((ulong)tcb, 0, 16);
tcbTreeItem->setToolTip(0, tip);
if (tcb == currTcb_ && !includeTasks)
tcbTreeItem->setBackgroundColor(0, QColor("salmon"));
if (parentTreeItem == NULL)
{
ui->treeWidget->clear();
ui->treeWidget->addTopLevelItem(tcbTreeItem);
}
else
{
parentTreeItem->addChild(tcbTreeItem);
}
itemDetails->currTcb = tcb;
itemDetails->currSched = sched;
itemDetails->currTask = NULL;
QVariant itemData = qVariantFromValue(itemDetails);
tcbTreeItem->setData(0, Qt::UserRole, itemData);
//set column alignment for each row
tcbTreeItem->setTextAlignment(1, Qt::AlignCenter | Qt::AlignVCenter);
tcbTreeItem->setTextAlignment(2, Qt::AlignCenter | Qt::AlignVCenter);
if (nodeText.compare(QString("NULL")))
{
tcbTreeItem->setText(1, QString(breakText));
tcbTreeItem->setText(2, QString(scheduledText));
}
displayTcbTasks(tcb, currSubtask, sched, includeTasks, tcbTreeItem);
for (Int32 i = arity - 1; i >= 0; i--)
{
const ex_tcb *childTcb = tcb->getChild(i);
displayTcbTree(childTcb, currSubtask, sched, includeTasks, tcbTreeItem);
}
if (parentTreeItem == NULL)
{
// make some final adjustments
ui->treeWidget->expandAll();
for (int i = 0; i < ui->treeWidget->columnCount(); i++)
{
ui->treeWidget->resizeColumnToContents(i);
int width = ui->treeWidget->columnWidth(i);
if (i == 2 && width > 70)
// restrict the last column (breakpoints)
// to a small size, otherwise the resize
// process expands it all the way
width = 70;
ui->treeWidget->setColumnWidth(i, width + 20);
}
}
} //tdbTree != NULL
}
void TCBTreeView::displayTcbTasks(const ex_tcb *tcb,
ExSubtask *currSubtask,
ExScheduler *sched,
bool expandTasks,
QTreeWidgetItem *tcbTreeItem)
{
ExSubtask *subtask = sched->getSubtasksForGui();
int numBreakpoints = 0;
std::string isScheduled;
while (subtask)
{
if (subtask->getTcb() == tcb)
{
if (expandTasks)
{
QString nodeTextData = QString(QLatin1String(subtask->getTaskName()));
QStringList rowValues;
rowValues.append(nodeTextData);
QTreeWidgetItem *taskTreeItem = new QTreeWidgetItem(rowValues);
TcbTreeDetails *itemDetails = new TcbTreeDetails(tcb, sched, subtask);
taskTreeItem->setIcon(0, QIcon(":/file/Resource/Main/T.bmp"));
QString tip = QString("%1@0x%2").arg(typeid(*subtask).name()).arg((ulong)subtask, 0, 16);
taskTreeItem->setToolTip(0, tip);
tcbTreeItem->addChild(taskTreeItem);
itemDetails->currTcb = tcb;
itemDetails->currSched = sched;
itemDetails->currTask = subtask;
QVariant itemData = qVariantFromValue(itemDetails);
taskTreeItem->setData(0, Qt::UserRole, itemData);
//set column alignment for each row
taskTreeItem->setTextAlignment(1, Qt::AlignCenter | Qt::AlignVCenter);
taskTreeItem->setTextAlignment(2, Qt::AlignCenter | Qt::AlignVCenter);
if (nodeTextData.compare(QString("NULL")))
{
setBreakSchedInfo(taskTreeItem,
(subtask->getBreakPoint() > 0 ? 1 : 0),
(subtask->isScheduled() ? "*" : ""));
if (subtask == currSubtask)
taskTreeItem->setBackgroundColor(0, QColor("salmon"));
}
} // expandTasks
else
{
// aggregate breakpoint and scheduled information at the task level
if (subtask->isScheduled())
numBreakpoints++;
if (subtask->getBreakPoint() > 0)
{
std::string taskText(subtask->getTaskName());
if (taskText.length() == 0 || taskText.at(0) == ' ')
taskText = "*";
taskText.append(",");
if (isScheduled.find(taskText) != std::string::npos)
{
isScheduled.append(subtask->getTaskName());
isScheduled.append(",");
}
}
} // don't list tasks in the tree view
} // task is for the current TCB
subtask = subtask->getNextForGUI();
} // loop over all subtasks
setBreakSchedInfo(tcbTreeItem, numBreakpoints, isScheduled.c_str());
}
void TCBTreeView::getOperatorImageText (const ComTdb *tdb,
Int32 & bitmapIndex,
QString &nodeText)
{
nodeText = QString("%1 (Id: %2 Ex: %3)").
arg(tdb->getNodeName()).
arg(tdb->getTdbId()).
arg(tdb->getExplainNodeId());
ComTdb::ex_node_type opType = tdb->getNodeType();
switch (opType)
{
case ComTdb::ex_ROOT:
bitmapIndex = IDX_ROOT;
break;
case ComTdb::ex_ONLJ:
case ComTdb::ex_MJ:
case ComTdb::ex_HASHJ:
case ComTdb::ex_TUPLE_FLOW:
bitmapIndex = IDX_JOIN;
break;
case ComTdb::ex_HBASE_ACCESS:
case ComTdb::ex_HDFS_SCAN:
bitmapIndex = IDX_SCAN;
break;
default:
bitmapIndex = IDX_GENERIC;
}
}
void TCBTreeView::setBreakSchedInfo(QTreeWidgetItem *treeItem,
int numBreakpoints,
const char *schedTasks)
{
std::string schedText(schedTasks);
if (numBreakpoints > 0)
{
treeItem->setText(1, QString("*"));
treeItem->setBackgroundColor(1,"orangered");
}
else
{
treeItem->setText(1, QString(" "));
}
if (schedText.length() > 0 && schedText.at(schedText.length()-1) == ',')
schedText.erase(schedText.length()-1);
if (schedText.length() > 16)
schedText = "*";
treeItem->setText(2, QString(schedText.c_str()));
if (schedText.length() > 0)
treeItem->setBackgroundColor(2,"lightblue");
}