IOHandler<DataObj, ParamObj>

dtl


IOHandler<DataObj, ParamObj>

Category: functors Component type: concept

Description

An IOHandler is a function object (or a wrapped function pointer if you use cb_ptr_fun_w_ret()) that is called when exceptions are thrown in DB_iterator operations. The handler uses the state of the iterator passed in to decide how to process the exception. After performing its work, the handler tells the iterator whether to suppress the error (dtl_ios_base::SUPPRESS_ERROR) or to re-throw the exception (dtl_ios_base::THROW_EXCEPTION). To use the IOHandler facility, declare your own handler class as shown in the examples below. To install a handler, pass your handler to the iterator's set_io_handler() function. For example, suppose your handler is of type MyHandler<DataObj, ParamObj> and you wish to pass it to an iterator called DB_iterator<DataObj, ParamObj> it. You would use set_io_handler() by saying: it.set_io_handler(MyHandler<DataObj, ParamObj>()). Later on, you may need to extract things such as an error log from your handler or other state information. To query your handler, extract it by invoking it.get_io_handler((MyHandler *) NULL). The dummy pointer is passed in to tell the compiler the type of the result of get_io_handler(). You can also set a default handler for a DBView so that all newly created iterators over that view will use this default handler if they don't explicitly install their own handler. To set the default handlder for a DBView call the get_io_handler() and set_io_handler() methods for the DBView. The handler for a DBView defaults to whatever handler is #defined as the macro DEFAULT_IO_HANDLER. If the user doesn't specify a default, then DTL sets the macro to be AlwaysThrowsHandler , which rethrows the exception. Finally, if you are working with an IndexedDBView you can call IndexedDBView::get_io_handler() to get the handler of the underlying DBView that it uses.

Definition

Defined in the DBView.h header file.

Associated types

AlwaysThrowsHandler, LoggingHandler.

Example 1:

A good example of an IOHandler: LoggingHandler


// *** Note: this is the actual LoggingHandler template from the DTL code ***

// this handler logs exceptions to a vector
// then tells caller to reperform the action
template<class DataObj, class ParamObj = DefaultParamObj<DataObj> > class LoggingHandler
{
public:
	struct LoggedTriple
	{
		string errmsg;
		DataObj dataObj;
		ParamObj paramObj;

		LoggedTriple() : errmsg(""), dataObj(), paramObj() { }

		LoggedTriple(const string &msg, const DataObj &data, const ParamObj &param) :
		  errmsg(msg), dataObj(data), paramObj(param) { }
	};

private:
	CountedPtr<vector<LoggedTriple> > errorLog;// all copies of the handler will share this error log
	
public:

	LoggingHandler() :
		  errorLog() { }
	
	dtl_ios_base::MeansOfRecovery
		operator()(RootException &ex, dtl_ios_base &base,
			DataObj &data, ParamObj &params)
	{
		// log the error
		errorLog.push_back(LoggedTriple(ex.what(), data, params));
		
		// tell the program to continue
		return dtl_ios_base::SUPPRESS_ERROR;
	}

	vector<LoggedTriple> GetLog() const
	{
		return errorLog;
	}

};
// Example Code Using LoggingHandler on a DBView

// test of failed SelValidate() when reading data
void TestBadSelValidate()
{
 	vector<Example> results;

	// construct view
	// DBView<Example> is actually DBView<Example, 
	// DefaultParamObj<Example> > thanks to the default 
	// argument to the DBView template

	// use our bad BCA which references a nonexistent column name in DB_EXAMPLE
	DBView<Example>
		view("DB_EXAMPLE", BCAExampleObj(),
		"WHERE INT_VALUE BETWEEN (?) AND (?) AND "
		"STRING_VALUE = (?) OR EXAMPLE_DATE < (?) ORDER BY EXAMPLE_LONG",
		BPAExampleObj(), BadSelValidate());

	view.set_io_handler(LoggingHandler<Example>());

	// loop through query results and add them to our vector
	// in this loop, read_it.GetLastCount() records read from DB

	DBView<Example>::select_iterator read_it = view.begin();

	// set parameter values for the WHERE clause in our SQL query
	read_it.Params().lowIntValue = 2;
	read_it.Params().highIntValue = 8;
	read_it.Params().strValue = "Example";
	
	TIMESTAMP_STRUCT paramDate = {2000, 1, 1, 0, 0, 0, 0};
	read_it.Params().dateValue = paramDate;

	for ( ; read_it != view.end(); read_it++)
	{
		try
		{
		  // note that the read_iterator::GetLastCount()  is incremented in operator++()
		  // remember that the record is fetched and thus the count incremented
		  // before operator*() is applied to the read_iterator

		  cout << "Reading element #" << read_it.GetLastCount() << endl;
		  
		  cout << "read_it->exampleInt = " << read_it->exampleInt << endl;
		  cout << "read_it->exampleStr = " << read_it->exampleStr << endl;
		  
		  results.push_back(*read_it);
		}
		catch (RootException &ex)
		{
		  cout << "Caught Exception!!!!" << endl;
		  cout << ex.what() << endl;
		}
	}

	LoggingHandler<Example> handler = 
		read_it.get_io_handler((LoggingHandler<Example> *) NULL);

	typedef LoggingHandler<Example>::LoggedTriple LoggedTriple;

	vector<LoggedTriple> errors = handler.GetLog();

	for (vector<LoggedTriple>::iterator log_it = errors.begin(); log_it != errors.end();
			log_it++)
	{
		LoggedTriple error = *log_it;

		cout << "Error msg = " << error.errmsg << endl;
		cout << "Example = " << error.dataObj << endl;
	}

}

Example 2: A Heroic Error Handler

// Let's Use our X-Ray Vision to Look at the Innards of our Hero


template<class DataObj, class ParamObj = DefaultParamObj<DataObj> > class OurHeroicHandler
{
private:
	// ... some state data, but assume handler is default constructible
public:

	dtl_ios_base::MeansOfRecovery
		operator()(RootException &ex, dtl_ios_base &base,
		   DataObj &data, ParamObj &params)
	{
		// example of what you might do in a handler
		if (bad())
		{
			LogErrorToFile(ex);
			return dtl_ios_base::THROW_EXCEPTION;
		}
		else if (fail())
		{
			// tries to make the DataObj valid and then reapplies previous operation
			// to base on the good object ... may still fail
			bool failed = WorkMagicOnDataObjAndTryAgain(...);

			if (failed)
			{
				LogErrorToFile(ex);
				return dtl_ios_base::THROW_EXCEPTION;
			}
			else
				return dtl_ios_base::SUPPRESS_ERROR; // success ... our superhero
								     // has saved the day!
		}
	}
};

Public Base Classes

None.

Template parameters

Parameter Description Default
DataObj The value type of objects in a DBView.  
ParamObj The type of object used to specify the postfix parameters to the DBView. DefaultParamObj<DataObj> 

 

Notation

X A type that is a model of IOHandler
a Object of type X

Expression semantics

Name Expression Precondition Semantics Postcondition
Default constructor
X a()
  Construct the function object.  
Copy constructor
X a(constX &b)
  Copy construct the IOHandler.  
UserHandler constructor
template<class UserHandler> a(const UserHandler hb)
  Construct the IOHandler using the user-defined handler ( it's type is bound to the UserHandler template parameter) passed in (the example classes above declare such handlers)..  
Assignment Operator X operator=(const X &b)   Assign the IOHandler.  
Handle exception operator
dtl_ios_base::MeansOfRecovery operator()(RootException &ex, dtl_ios_base &base, DataObj &data, ParamObj &params)
  This operator takes references to the thrown RootException object, the dtl_ios_base (iterator) which threw, and the DataObj and ParamObj relevant to the exception. Handles the exception and then returns whether the iterator should suppress the error (dtl_ios_base::SUPPRESS_ERROR) or whether to still throw the exception (dtl_ios_base::THROW_EXCEPTION).  
Get UserHandler
template<class UserHandler> const UserHandler &
   get(const UserHandler *dummy) const
  Returns the user-defined handler ( it's type is bound to the UserHandler template parameter). You must pass in a pointer to your user-defined handler's type so the compiler knows what type UserHandler should be as in:

MyHandler my_handler = io_handler.get((MyHandler *) NULL);

 

 

Notes

See also

AlwaysThrowsHandler, LoggingHandler, DBView, IndexedDBView


[DTL Home]

Copyright © 2002, Michael Gradman and Corwin Joy.

Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appears in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Corwin Joy and Michael Gradman make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.

This site written using the ORB. [The ORB]

1