/*
   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
*/

#ifndef WakeupHandler_H
#define WakeupHandler_H

#include <ndb_types.h>
class Ndb;
class Ndb_cluster_connection;
class PollGuard;

/**
 * WakeupHandler
 *
 * Help Ndb objects respond to wakeups from the TransporterFacade
 * when transactions have completed.
 *
 * Each Ndb will own an instance of the DefaultWakeupHandler,
 * and each NdbWaitGroup will create an instance of a more specialized
 * WakeupHandler.
 */

class WakeupHandler
{
public:
  virtual void notifyTransactionCompleted(Ndb* from) = 0;
  virtual void notifyWakeup() = 0;
  virtual ~WakeupHandler() {};
};

class MultiNdbWakeupHandler : public WakeupHandler
{
public:
  MultiNdbWakeupHandler(Ndb* _wakeNdb);
  ~MultiNdbWakeupHandler();
  bool unregisterNdb(Ndb *);
  bool ndbIsRegistered(Ndb *);
  void notifyTransactionCompleted(Ndb* from);
  void notifyWakeup();
  Uint32 getNumReadyNdbs() const;
  /** returns 0 on success, -1 on timeout: */
  int waitForInput(Ndb **objs, int cnt, int min_requested,
                   PollGuard* pg, int timeout_millis);

private:   // private methods
  void swapNdbsInArray(Uint32 indexA, Uint32 indexB);
  bool isReadyToWake() const;

private:   // private instance variables
  Uint32 numNdbsWithCompletedTrans;
  Uint32 minNdbsToWake;
  Ndb* wakeNdb;
  Ndb** objs;
  Uint32 cnt;
  volatile bool woken;
};


inline bool MultiNdbWakeupHandler::isReadyToWake() const
{
  return (numNdbsWithCompletedTrans >= minNdbsToWake) || woken;
}

#endif
