text: /* 
   Copyright (C) GridGain Systems. All Rights Reserved.
   
   Licensed 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.
   */
  
  /*  _________        _____ __________________        _____
   *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
   *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
   *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
   *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
   */
  
  #ifndef GRID_CLIENT_IMPL_HPP_INCLUDED
  #define GRID_CLIENT_IMPL_HPP_INCLUDED
  
  #include <vector>
  #include <string>
  #include <memory>
  
  #include "gridgain/gridclient.hpp"
  #include "gridgain/impl/gridclientshareddata.hpp"
  #include "gridgain/impl/gridclientrecurringeventthread.hpp"
  #include "gridgain/impl/gridclientdataprojection.hpp"
  #include "gridgain/impl/gridclientcomputeprojection.hpp"
  #include "gridgain/impl/gridclientprojectionlistener.hpp"
  #include "gridgain/impl/utils/gridthreadpool.hpp"
  
  /**
   * Client implementation.
   */
  class GridClientImpl : public GridClient, public GridClientProjectionListener {
  public:
      /**
       * Public constructor.
       *
       * @param cfg Client configuration.
       * @param exec Executor of the commands.
       */
      GridClientImpl(const GridClientConfiguration& cfg, std::shared_ptr<GridClientCommandExecutorPrivate>& exec);
  
      /**
       * Gets a unique client identifier. This identifier is generated by factory on client creation
       * and used in identification and authentication procedure on server node.
       *
       * @return Generated client id.
       */
      virtual GridClientUuid id() const;
  
      /**
       * Gets a data projection for a default grid cache with <tt>null</tt> name.
       *
       * @return Data projection for grid cache with <tt>null</tt> name.
       * @throw GridClientException If client was closed.
       */
      virtual TGridClientDataPtr data();
  
      /**
       * Gets a data projection for grid cache with name <tt>cacheName</tt>. If
       * no data configuration with given name was provided at client startup, an
       * exception will be thrown.
       *
       * @param cacheName Grid cache name for which data projection should be obtained.
       * @return Data projection for grid cache with name <tt>cacheName</tt>.
       * @throw GridClientException If client was closed or no configuration with given name was provided.
       */
      virtual TGridClientDataPtr data(const std::string& cacheName);
  
      /**
       * Gets a default compute projection. Default compute projection will include all nodes
       * in remote grid. Selection of node that will be connected to perform operations will be
       * done according to {@link GridClientLoadBalancer} provided in client configuration or
       * according to affinity if projection call involves affinity key.
       * <p>
       * More restricted projection configurations may be created with {@link GridClientCompute} methods.
       *
       * @return Default compute projection.
       *
       * @see GridClientCompute
       */
      virtual TGridClientComputePtr compute();
  
      /**
       * Adds topology listener. Remote grid topology is refreshed every
       * {@link GridClientConfiguration#getTopologyRefreshFrequency()} milliseconds. If any node was added or removed,
       * a listener will be notified.
       *
       * @param lsnr Listener to add.
       */
      virtual void addTopologyListener(TGridClientTopologyListenerPtr lsnr);
  
      /**
       * Removes previously added topology listener.
       *
       * @param lsnr Listener to remove.
       */
      virtual void removeTopologyListener(TGridClientTopologyListenerPtr lsnr);
  
      /**
       * Gets an unmodifiable snapshot of topology listeners list.
       *
       * @return List of topology listeners.
       */
      virtual TGridClientTopologyListenerListPtr topologyListeners() const;
  
      /**
       * Closes client.
       * @param waitCompletion If <tt>true</tt>will wait for all pending requests to be proceeded.
       */
      virtual void stop(bool waitCompletion = true);
  
      /**
       * @param n Node.
       */
      void onNodeIoFailed(const GridClientNode& n);
  
  protected:
      /**  Returns the client shared data. */
      TGridClientSharedDataPtr getSharedData() const {
          return sharedData;
      }
  
      /** The link to the main compute projection. */
      std::shared_ptr<GridClientComputeProjectionImpl> mainComputePrj;
  
      /** Typedef for link to the main data projection. */
      //typedef std::map<std::string, TGridClientDataPtr > TDataPrjMap;
      typedef std::map<std::string, std::shared_ptr<GridClientDataProjectionImpl> > TDataPrjMap;
  
      /** The link to the main data projection.*/
      TDataPrjMap mainDataPrjs;
  
  private:
      /** Refresh the topology by the given configuration and executor. */
      void refreshTopology();
  
      /**
       * Returns client data, creating it if needed.
       *
       * @param cacheName Cache name.
       * @return Shared pointer to client data.
       */
      TGridClientDataPtr getOrCreateDataProjection(std::string cacheName);
  
      /**
       * Fires the topology events for an updated nodes set.
       *
       * @param updNodes Updated nodes set.
       * @param prevNodes Previous nodes set version.
       */
      void fireTopologyEvents(const TNodesSet& updNodes, const TNodesSet& prevNodes);
  
      /**
       * Fires onNodeAdded() event on topology listeners.
       *
       * @param node Added node.
       */
      void fireNodeAdded(const GridClientNode& node);
  
      /**
       * Fires onNodeRemoved() event on topology listeners.
       *
       * @param node Removed node.
       */
      void fireNodeRemoved(const GridClientNode& node);
  
      /** Client shared data. */
      TGridClientSharedDataPtr sharedData;
  
      /** GridClientTopologyRefresher may call non-public methods. */
      friend class GridClientTopologyRefresher;
  
      /** Refresh topology thread class. */
      class GridClientTopologyRefresher : public GridClientRecurringEventThread::EventListener {
      public:
          /**
           * Public constructor.
           *
           * @param topRefreshFreq Topology refresh frequency in milliseconds.
           * @param pClient Client to refresh.
           */
          GridClientTopologyRefresher(long topRefreshFreq, GridClientImpl& pClient)
              : refreshThread(topRefreshFreq, *this), client(pClient) {
          }
  
          /**
           * Method called when timer event is received.
           */
          virtual void onTimerEvent();
  
      private:
          /** Refresh thread. */
          GridClientRecurringEventThread refreshThread;
  
          /** Client. */
          GridClientImpl& client;
      };
  
      /** Topology refresher for this client. */
      std::shared_ptr<GridClientTopologyRefresher> topRefresher;
  
      /** Thread pool to execute async operations. */
      TGridThreadPoolPtr threadPool;
  
      /** Topology listeners. */
      std::vector<TGridClientTopologyListenerPtr> topLsnrs;
  
      /** Topology listeners mutex. */
      mutable boost::mutex topLsnrsMux;
  };
  
  #endif
  