Source: ../../libxorp/transaction.hh


 
LOGO
 Annotated List  Files  Globals  Hierarchy  Index  Top
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-

// Copyright (c) 2001-2005 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.

// $XORP: xorp/libxorp/transaction.hh,v 1.7 2005/07/29 20:06:33 bms Exp $

#ifndef __LIBXORP_TRANSACTION_HH__
#define __LIBXORP_TRANSACTION_HH__

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <map>
#include <list>
#include <string>

#include "libxorp/eventloop.hh"
#include "libxorp/ref_ptr.hh"

/**
 * @short Base class for operations within a Transaction.
 *
 * TransactionOperations when realized through derived classes are
 * operations that can be held and dispatched at a later time.  The
 * @ref TransactionManager class is provided as a container for
 * TransactionOperations.
 *
 * NB TransactionOperation is analogous to the Command pattern in the
 * BoF: Design Patterns , Erich Gamma, Richard Helm, Ralph Johnson,
 * John Vlissides, Addison Wesley, 1995, ISBN 0-201-63361-2.
 */
class TransactionOperation {
public:
    /**
     * Destructor
     */
    virtual ~TransactionOperation() {}

    /**
     * Dispatch operation
     * 
     * @return true on success, false on error.
     */
    virtual bool dispatch() = 0;

    /**
     * @return string representation of operation.
     */
    virtual string str() const = 0;
};

/**
 * @short A class for managing transactions.
 *
 * The TransactionManager creates, manages, and dispatches
 * transactions.  A Transaction is comprised of a sequence of @ref
 * TransactionOperation s.  Each transaction is uniquely identified by
 * a transaction id.
 */
class TransactionManager {
public:
    typedef ref_ptr<TransactionOperation> Operation;

    /**
     * Constuctor with a given event loop, timeout, and max pending commits.
     *
     * @param e the EventLoop instance.
     * 
     * @param timeout_ms the inter-operation addition timeout.  If zero,
     *        timeouts are not used, otherwise a timeout will occur
     *	      and the transaction aborted if the transaction is not
     *	      updated for timeout_ms.
     *
     * @param max_pending the maximum number of uncommitted transactions
     *        pending commit.
     */
    TransactionManager(EventLoop& e,
		       uint32_t timeout_ms = 0,
		       uint32_t max_pending = 10) : 
	_e(e), _timeout_ms(timeout_ms), _max_pending(max_pending) 
    {
    }

    /**
     * Destructor
     */
    virtual ~TransactionManager() {}

    /**
     * Start transaction
     *
     * @param new_tid variable to assigned new transaction id.
     * 
     * @return true on success, false if maximum number of pending 
     * 		    transactions is reached.
     */
    bool start(uint32_t& new_tid);

    /**
     * Commit transaction
     * 
     * @param tid the transaction ID.
     * @return true on success, false on error.
     */
    bool commit(uint32_t tid);

    /**
     * Abort transaction
     * 
     * @param tid the transaction ID.
     * @return true on success, false on error.
     */
    bool abort(uint32_t tid);

    /**
     * Add operation to transaction.
     *
     * @param tid the transaction ID.
     * @param operation to be added.
     * @return true on success, false if tid is invalid.
     */
    virtual bool add(uint32_t tid, const Operation& op);

    /**
     * Retrieve number of operations in pending transaction.
     *
     * @param tid the transaction ID.
     *
     * @param count variable to be assigned number of operations in 
     * transaction.
     *
     * @return true if tid is valid, false otherwise.
     */
    bool retrieve_size(uint32_t tid, uint32_t& count) const;

    /**
     * Get the inter-operation additional timeout.
     * 
     * If the inter-operation addition timeout is zero,
     * timeouts are not used, otherwise a timeout will occur
     * and the transaction aborted if the transaction is not
     * updated for timeout_ms.
     * 
     * @return the inter-operation additional timeout.
     */
    inline uint32_t timeout_ms() const 	{ return _timeout_ms; }

    /**
     * Get the maximum number of uncommited pending transactions.
     * 
     * @return the maximum number of uncommitted transactions pending commit.
     */
    inline uint32_t max_pending() const { return _max_pending; }

    /**
     * Get the current number of uncommited pending transactions.
     * 
     * @return the current number of uncommitted transactions pending commit.
     */
    inline uint32_t pending() const 	{ return _transactions.size(); }

protected:

    /**
     * Overrideable function that can be called before the first
     * operation in a commit is dispatched.
     *
     * Default implementation is a no-op.
     */
    virtual void pre_commit(uint32_t tid);

    /**
     * Overrideable function that can be called after commit occurs 
     *
     * Default implementation is a no-op.
     */
    virtual void post_commit(uint32_t tid);

    /**
     * Overrideable function that is called immediately after an individual
     * operation is dispatched.
     *
     * Default implementation is a no-op.
     *
     * @param success whether the operation succeed.
     *
     * @param op the operation.
     */
    virtual void operation_result(bool success, 
				  const TransactionOperation& op);

    /**
     * Flush operations in transaction list.  May be use by @ref
     * operation_result methods to safely prevent further operations
     * being dispatched when errors are detected.  flush() always
     * succeeds if transaction exists.
     *
     * @param tid transaction id of transaction to be flushed.
     *
     * @return true if transaction exists, false otherwise.
     */
    bool flush(uint32_t tid);
    
protected:
    /**
     * Transaction class, just a list of operations to be dispatched.
     * 
     * It is defined here so classes derived from TransactionManager
     * can operate, eg sort operations in list, before committing transaction.
     */
    struct Transaction {
	typedef list<Operation> OperationList;
	
	Transaction(TransactionManager& mgr, const XorpTimer& timeout_timer)
	    : _mgr(mgr), _timeout_timer(timeout_timer), _op_count(0)
	{}

	Transaction(TransactionManager& mgr) : _mgr(mgr), _op_count(0)
	{}

	/** Add an operation to list */
	inline void add(const Operation& op);

	/** Dispatch all operations on list */
	inline void commit();

	/** Flush all operations on list */
	inline void flush();
	
	/** Defer timeout by TransactionManagers timeout interval */
	inline void defer_timeout();

	/** Cancel timeout timer */
	inline void cancel_timeout();
	
	/** Get the list of operations */
	inline OperationList& operations() { return _ops; }

	/** Get the length of the operations list. */
	inline uint32_t size() const { return _op_count; }
	
    private:
	TransactionManager& _mgr;
	OperationList	    _ops;
	XorpTimer	    _timeout_timer;
	uint32_t	    _op_count;
    };

private:
    /** Called when timeout timer expires */
    void timeout(uint32_t tid);

    /** Increment next transaction id by a randomized amount. */
    void crank_tid();

private:
    typedef map<uint32_t, Transaction> TransactionDB;

    EventLoop& _e;
    TransactionDB _transactions;
    uint32_t _timeout_ms;
    uint32_t _max_pending;
    uint32_t _next_tid;
    
    friend class Transaction; // for Transaction to call operation_result()
};

#endif // __LIBXORP_TRANSACTION_HH__

Generated by: pavlin on possum.icir.org on Thu Mar 9 04:41:55 2006, using kdoc $.