blob: 7d0c39b25c6d08e1422dcc60ab38bdb2574b06e4 [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 @@@
//
**********************************************************************/
#ifndef _RU_TASK_H_
#define _RU_TASK_H_
/* -*-C++-*-
******************************************************************************
*
* File: RuTask.h
* Description: Definition of class CRUTask.
*
* Created: 8/23/1999
* Language: C++
*
*
******************************************************************************
*/
//--------------------------------------------------------------------------//
// CRUTask
//
// A generic runtime task abstract class.
//
// This class supports connectivity in the dependence graph.
// The CRUTask object maintains a list of tasks that depend on this
// task (pSuccList_) and a list of tasks that this task depends on
// (pPredList_), and provides the API to add and remove dependencies
// (edges in the graph).
//
// The meaning of an edge A-->B is that task B cannot be executed
// before task A.
//
// CRUTask does not support task execution directly. Rather,
// a lightweight task executor (CRUTaskExecutor object) is built.
// The executor will carry the concrete task's context, and can be
// executed either in the main (arkcmp) process, or in a task process.
//
// Every class derived from CRUTask will be associated with one or more
// objects (which inherit from CRUObject). If any errors happen about the
// task's execution, the error message will be stored in the task object.
//
// Tasks can compute their own *costs*, which affect the utility scheduler's
// decisions.
//
// The task object will hold the process id of the task process
// (in the UOFS process pool) that executes the task.
//
//--------------------------------------------------------------------------//
#include "refresh.h"
#include "dsptrlist.h"
#include "RuException.h"
class CRUTaskExecutor;
class CRUTaskList;
class REFRESH_LIB_CLASS CRUTask {
//---------------------------------------//
// PUBLIC AREA
//---------------------------------------//
public:
enum Type {
REFRESH = 0,
TABLE_SYNC = 1,
DUP_ELIM = 2,
LOG_CLEANUP = 3,
RC_RELEASE = 4,
EMP_CHECK = 5,
LOCK_EQUIV_SET = 6
};
// Dummy cost value, if want to set a task's cost to artificially high
enum
{
MAX_COST = 65536
};
public:
CRUTask(Lng32 taskId);
virtual ~CRUTask();
//-----------------------------------//
// Accessors
//-----------------------------------//
public:
// Unique task identifier
Lng32 GetId() const
{
return taskId_;
}
// To be applied after building the executor.
CRUTaskExecutor &GetExecutor() const
{
RUASSERT (NULL != pExecutor_);
return *pExecutor_;
}
BOOL IsRunning() const
{
return isRunning_;
}
// Did the executor run
BOOL WasExecuted() const
{
return wasExecuted_;
}
// NOT TO CONFUSE WITH COST!
// The gain is function of the cost of both
// the task itself and the tasks that depend on it.
TInt32 GetGain() const
{
return gain_;
}
public:
// Framework for error reporting mechanism
CRUException &GetErrorDesc()
{
return errorDesc_;
}
Lng32 GetStatus()
{
return GetErrorDesc().GetStatus();
}
public:
//---- Connectivity queries ----//
// What are the tasks that I depend on?
CRUTaskList& GetTasksThatIDependOn() const
{
return *pPredList_;
}
// What are the tasks that depend on me?
CRUTaskList& GetTasksThatDependOnMe() const
{
return *pSuccList_;
}
// Are there no tasks that I depend on?
BOOL IsReady() const;
public:
//-- Pure virtuals - delegated to derived classes
virtual Type GetType() const = 0;
virtual CDSString GetTaskName() const = 0;
// Does the task operate on an object with a given UID?
virtual BOOL HasObject(TInt64 uid) const = 0;
#ifdef _DEBUG
public:
void Dump(CDSString &to);
void DumpGraphNode(CDSString &to);
void DumpGraphEdges(CDSString &to);
#endif
//-----------------------------------//
// Mutators
//-----------------------------------//
public:
void SetRunning(BOOL val)
{
isRunning_ = val;
}
void SetExecuted(BOOL val)
{
wasExecuted_ = val;
}
// Build the executor object.
void BuildExecutor();
// After the execution, the executor can be released
void DeleteExecutor();
//-- Heuristics computation
// The gain computation heuristic is the same for every type
void ComputeGain();
public:
//---- Connectivity updates ----//
void AddTaskThatIDependOn(CRUTask *pTask);
void RemoveTaskThatIDependOn(CRUTask *pTask);
void AddTaskThatDependsOnMe(CRUTask *pTask);
void RemoveTaskThatDependsOnMe(CRUTask *pTask);
void RemoveAllTasksThatDependOnMe();
void RemoveAllTasksThatIDependOn();
public:
//-- Predecessor/Successor task failure handlers
// BOTH ARE VIRTUAL AND CAN BE OVERRIDDEN
// Default behavior when the predecessor fails -
// propagate the error to myself
virtual void HandlePredecessorFailure(CRUTask &task);
// Default behavior when the successor fails - nothing
virtual void HandleSuccessorFailure(CRUTask &task) {}
//---------------------------------------//
// PROTECTED AND PRIVATE AREA
//---------------------------------------//
protected:
// The task's cost. If the task is not immediate,
// this is the estimate of its running time.
virtual TInt32 GetComputedCost() const = 0;
// Is this a very short task
// (to be executed in the arkcmp process) ?
virtual BOOL IsImmediate() const = 0;
protected:
// BuildExecutor() callee
// Create the concrete executor's object.
// Delegated to the child classes
virtual CRUTaskExecutor *CreateExecutorInstance() = 0;
// DeleteExecutor() callee
// Before the executor is deleted - pull from it whatever is required.
// The default behavior is DO NOTHING - can be overridden.
virtual void PullDataFromExecutor() {}
private:
// Generic cost computation mechanism
void ComputeCost();
TInt32 GetCost() const
{
return cost_;
}
//---------------------------------------//
// Core data members
//---------------------------------------//
private:
Lng32 taskId_;
CRUException errorDesc_;
// Connectivity lists
CRUTaskList *pPredList_;
CRUTaskList *pSuccList_;
// The task's executor
CRUTaskExecutor *pExecutor_;
BOOL isRunning_;
BOOL wasExecuted_;
TInt32 cost_;
TInt32 gain_;
// Process id (in the process pool) associated with the task
short pid_;
};
//--------------------------------------------------------------------------//
// CRUTaskList
//
// List of pointers to task objects.
// Supports searching by task Id and smart update.
//--------------------------------------------------------------------------//
class REFRESH_LIB_CLASS CRUTaskList : public CDSPtrList<CRUTask> {
private:
typedef CDSPtrList<CRUTask> inherited;
public:
CRUTaskList(EOwnership ownership = eItemsAreOwned)
: inherited(ownership) {}
~CRUTaskList() {}
//-----------------------------------//
// Accessors
//-----------------------------------//
public:
CRUTask *FindTask(Lng32 taskId);
DSListPosition FindTaskPos(Lng32 taskId);
//-----------------------------------//
// Mutators
//-----------------------------------//
public:
void AddRefToTask(CRUTask *pTask);
void RemoveRefToTask(CRUTask *pTask);
};
//--------------------------------------------------------------------------//
// The inliners
//--------------------------------------------------------------------------//
inline BOOL CRUTask::IsReady() const
{
return (0 == GetTasksThatIDependOn().GetCount());
}
#endif