iscope.hpp

Go to the documentation of this file.
00001 /*
00002 This file is part of GraphLab.
00003 
00004 GraphLab is free software: you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as 
00006 published by the Free Software Foundation, either version 3 of 
00007 the License, or (at your option) any later version.
00008 
00009 GraphLab is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public 
00015 License along with GraphLab.  If not, see <http://www.gnu.org/licenses/>.
00016 */
00017 
00018 /** \file 
00019  *
00020  * This file describes the iscope interface as well as the the
00021  * scope_range_enum.
00022  *
00023  */
00024 #ifndef GRAPHLAB_SCOPE_HPP
00025 #define GRAPHLAB_SCOPE_HPP
00026 
00027 #include <set>
00028 #include <vector>
00029 #include <cassert>
00030 
00031 #include <graphlab/graph/graph.hpp>
00032 
00033 
00034 #include <graphlab/macros_def.hpp>
00035 namespace graphlab {
00036 
00037   /** \brief defines the types of scope consistency guarantees provided  
00038    
00039       There are several choices for consistency mechanisms in the
00040       graphlab framework.  Each choice determines to what extent
00041       adjacent vertices can be operated on in parallel.  
00042 
00043       <ul> 
00044 
00045         <li> Null Consistency: provides no guarantees allowing update
00046         functions to operate on the same vertex concurrently </li>
00047 
00048         <li> Vertex Read Consistency: On ensures that that you can
00049         read from the local vertex correctly</li>
00050 
00051         <li> Vertex Consistency: Ensures that a scope is aquired by
00052         only one processor at a time </li>
00053 
00054         <li> Edge Consistency: Ensures that adjacent vertices are not
00055         updated simultaneoulsy. If the update function only modifies
00056         the data on the scope vertex and its adjacent edges then this
00057         consistency model is sufficient to guarantee sequential
00058         consistency </li>
00059 
00060         <li> Fully Consistency: This consistency models guarantees
00061         sequential consistency but may limit the available
00062         parallelism.  Effectively, this consistency model ensures that
00063         overlapping scopes cannot be executed simultaneously.</li>
00064 
00065       </ul>
00066 
00067       The scope_range_enum is passed to the engine through the iengine
00068       interface or set using the engine factory.
00069  
00070    */
00071   struct scope_range {
00072     /// \brief scope types
00073     enum scope_range_enum {
00074       NULL_CONSISTENCY = 0,    ///< no locks
00075       VERTEX_READ_CONSISTENCY, ///< read only from self
00076       READ_CONSISTENCY,        ///< read from self and adjacent structures
00077       VERTEX_CONSISTENCY,      ///< write to self. no lock on adjacent
00078       EDGE_CONSISTENCY,        ///< write to self, read from adjacent structures
00079       FULL_CONSISTENCY,        ///< write to self and adjacent structures
00080       USE_DEFAULT
00081     };
00082     
00083     enum lock_type_enum {
00084       NO_LOCK = 0,
00085       READ_LOCK = 1,
00086       WRITE_LOCK = 2
00087     };
00088   };
00089 
00090   inline scope_range::lock_type_enum central_vertex_lock_type(scope_range::scope_range_enum srange) {
00091     switch (srange) {
00092       case scope_range::NULL_CONSISTENCY:
00093         return scope_range::NO_LOCK;
00094       case scope_range::VERTEX_READ_CONSISTENCY:
00095       case scope_range::READ_CONSISTENCY:
00096         return scope_range::READ_LOCK;
00097       case scope_range::VERTEX_CONSISTENCY:
00098       case scope_range::EDGE_CONSISTENCY:
00099       case scope_range::FULL_CONSISTENCY:
00100         return scope_range::WRITE_LOCK;
00101       default:
00102         assert(false);
00103         // unreachable
00104         return scope_range::NO_LOCK;
00105     }
00106   }
00107 
00108   inline scope_range::lock_type_enum adjacent_vertex_lock_type(scope_range::scope_range_enum srange) {
00109     switch (srange) {
00110       case scope_range::NULL_CONSISTENCY:
00111       case scope_range::VERTEX_READ_CONSISTENCY:
00112       case scope_range::VERTEX_CONSISTENCY:
00113         return scope_range::NO_LOCK;
00114       case scope_range::READ_CONSISTENCY:
00115       case scope_range::EDGE_CONSISTENCY:
00116         return scope_range::READ_LOCK;
00117       case scope_range::FULL_CONSISTENCY:
00118         return scope_range::WRITE_LOCK;
00119       default:
00120         assert(false);
00121         // unreachable
00122         return scope_range::NO_LOCK;
00123     }
00124   }
00125 
00126 
00127   inline bool scope_is_subset_of(scope_range::scope_range_enum A,
00128                                  scope_range::scope_range_enum B) {
00129     /*
00130     if (A==scope_range::READ_CONSISTENCY && B == scope_range::VERTEX_CONSISTENCY) return false;
00131     else return (A < B);*/
00132     
00133     return (!(A==scope_range::READ_CONSISTENCY && B == scope_range::VERTEX_CONSISTENCY)) && (A < B);
00134   }
00135 
00136   /**
00137    * \brief represents the data associated with a vertex its adjacent
00138    * edges and neighbors.
00139    *
00140    * The update function is passed an instance of iscope and is uses
00141    * that instance to obtain information about the graph structure and
00142    * to read and modify the graph data.
00143    */
00144   template<typename Graph>
00145   class iscope {
00146   public:
00147     //! The type of graph that the iscope operates on
00148     typedef Graph graph_type;
00149 
00150     //! The vertex data type associated with the graph
00151     typedef typename Graph::vertex_data_type vertex_data_type;
00152 
00153     //! The edge data type associated with the graph
00154     typedef typename Graph::edge_data_type   edge_data_type;
00155 
00156     //! The edge data type associated with the graph
00157     typedef typename Graph::edge_list_type   edge_list_type;
00158 
00159 
00160 
00161   public:    
00162 
00163     /** 
00164      * \brief construct an iscope from a graph This is called by the
00165      * engine when creating an iscope to be passed into an update
00166      * function.
00167      */
00168     iscope(Graph* graph_ptr = NULL, vertex_id_t vertex = -1) : 
00169       _graph_ptr(graph_ptr), _vertex(vertex) {
00170     }
00171     
00172     /** iscope destructor */
00173     virtual ~iscope() { }
00174     
00175     /**
00176      * \brief commits all changes.
00177      * This is called by the engine after the update function returns.
00178      */
00179     virtual void commit() = 0;
00180 
00181     /**
00182      * Get the number of vertices in the graph
00183      */
00184     size_t num_vertices() const {
00185       assert(_graph_ptr != NULL);
00186       return _graph_ptr->num_vertices();  
00187     }
00188 
00189     
00190     /**
00191      * \brief Returns the vertex id of the base vertex in this scope.
00192      *
00193      * This method is used by the update function to get the base
00194      * vertex of the scope.  The base vertex is the vertex that the
00195      * update function is being applied to.
00196      */
00197     vertex_id_t vertex() const { return _vertex; }
00198 
00199     /** 
00200      * \brief edge lookup from source target pair to edge id.
00201      *
00202      * This is used to get structural information from the graph.  If
00203      * the edge is not present this method will fail. 
00204      */
00205     edge_id_t edge(vertex_id_t source,
00206                    vertex_id_t target) const {
00207       assert(_graph_ptr != NULL);
00208       // No cheating
00209       // assert(source == _vertex || target == _vertex);
00210       return _graph_ptr->edge_id(source, target);
00211     }
00212 
00213     /**
00214      * \brief test whether an edge is present
00215      *
00216      * This method tests whether the edge exists.  If the edge exists
00217      * this method returns true.  
00218      */
00219     bool edge_exists(vertex_id_t source,
00220                      vertex_id_t target) const {
00221       assert(_graph_ptr != NULL);
00222       // No cheating
00223       // assert(source == _vertex || target == _vertex);
00224       return _graph_ptr->find(source, target).first;
00225     }
00226     
00227 
00228     /**
00229      * \brief Get the reverse edge.
00230      *
00231      * Get the reverse edge id.  If no such edge exists this method
00232      * will fail. 
00233      */
00234     edge_id_t reverse_edge(edge_id_t eid) const {      
00235       assert(_graph_ptr != NULL);      
00236       //       // No cheating
00237       //       assert(_graph_ptr->source(eid) == _vertex ||
00238       //              _graph_ptr->target(eid) == _vertex);
00239       return _graph_ptr->rev_edge_id(eid);
00240     }
00241 
00242     /** 
00243      * \brief get all in edges to the base vertex of this scope. 
00244      * 
00245      * This method returns an immutable vector of edge ids sorted in
00246      * order of <source id, dest id> pairs.
00247      */
00248     edge_list_type in_edge_ids() const {
00249       assert(_graph_ptr != NULL);
00250       return _graph_ptr->in_edge_ids(_vertex);
00251     }
00252 
00253     /** 
00254      * \brief get all in edge ids to the vertex argument
00255      *
00256      * This method returns an immutable vector of edge ids sorted in
00257      * order of <source id, dest id> pairs.
00258      */
00259     edge_list_type in_edge_ids(vertex_id_t v) const {
00260       assert(_graph_ptr != NULL);
00261       return _graph_ptr->in_edge_ids(v);
00262     }
00263 
00264 
00265     /** 
00266      * \brief get all out edge ids to the base vertex of this scope
00267      *
00268      * This method returns an immutable vector of edge ids sorted in
00269      * order of <source id, dest id> pairs.
00270      */
00271     edge_list_type out_edge_ids() const {
00272       assert(_graph_ptr != NULL);
00273       return _graph_ptr->out_edge_ids(_vertex);
00274     }
00275 
00276     /** 
00277      * \brief get all out ede ids to the vertex argument.
00278      *
00279      * This method returns an immutable vector of edge ids sorted in
00280      * order of <source id, dest id> pairs.
00281      */
00282     edge_list_type out_edge_ids(vertex_id_t v) const {
00283       assert(_graph_ptr != NULL);
00284       return _graph_ptr->out_edge_ids(v);
00285     }
00286 
00287     //! Get the source vertex of the edge id argument
00288     vertex_id_t source(edge_id_t edge_id) const {
00289       //      assert(_graph_ptr != NULL);
00290       return _graph_ptr->source(edge_id);
00291     }
00292 
00293     //! get the target vertex of the edge id argument
00294     vertex_id_t target(edge_id_t edge_id) const {
00295       //       assert(_graph_ptr != NULL);
00296       return _graph_ptr->target(edge_id);
00297     }
00298     
00299     /**
00300      * \brief Get a mutable reference to the data associated with the
00301      * base vertex
00302      *
00303      * Certain optimizations may be made in future version of graphlab
00304      * that could benefit from immutable vertex_data requests.
00305      * Therefore if the vertex data does not need to be mutable use
00306      * the const reference version of vertex_data.
00307      */
00308     virtual vertex_data_type& vertex_data() = 0;
00309 
00310     /**
00311      * \brief Get an immutable reference to the data associated with
00312      * the vase vertex.
00313      * \deprecated use const_vertex_data
00314      * This should be called if the data does not need to be modified.
00315      */
00316     virtual const vertex_data_type& vertex_data() const = 0;
00317     
00318     /**
00319      * \brief Get an immutable reference to the data associated with
00320      * the vase vertex.
00321      *
00322      * This should be called if the data does not need to be modified.
00323      */    
00324     virtual const vertex_data_type& const_vertex_data() const = 0;
00325     
00326     
00327     /**
00328      * \brief Get a mutable reference to the data associated with the
00329      * edge.
00330      *
00331      * This should only be invoked on edges that are adjacent to the
00332      * base vertex.  If the edge_data is not going to be modified the
00333      * const version of this function should be used to permit further
00334      * optimization.
00335      */
00336     virtual edge_data_type& edge_data(edge_id_t eid) = 0;
00337 
00338     /**
00339      * \brief Get an immutable reference to the data associated with
00340      * the edge.
00341      * \deprecated use const_edge_data
00342      * This should only be invoked on edges that are adjacent to the
00343      * base vertex. 
00344      */
00345     virtual const edge_data_type& edge_data(edge_id_t eid) const = 0;
00346     
00347     
00348     /**
00349      * \brief Get an immutable reference to the data associated with
00350      * the vase vertex.
00351      *
00352      * This should be called if the data does not need to be modified.
00353      */    
00354     virtual const edge_data_type& const_edge_data(edge_id_t eid) const = 0;
00355     
00356     /**
00357      * \brief get a mutable reference to the data associated with a
00358      * neighboring vertex.
00359      *
00360      * This function should only be invoked on neighboring
00361      * vertices. Unfortunately, due to the Log(d) lookup required to
00362      * enforce the adjacency constraint we do not check at this time.
00363      * If the neighboring vertex data is not going to be modified the
00364      * const version of this function should be called to permit
00365      * further optimization by the graphlab engine.
00366      */
00367     virtual vertex_data_type& neighbor_vertex_data(vertex_id_t vertex) = 0;
00368 
00369     /**
00370      * \brief get an immutable reference to the data associated with a
00371      * neighboring vertex.
00372      * \deprecated Use const_neighbor_vertex_data
00373      * This function should only be invoked on neighboring
00374      * vertices. Unfortunately, due to the Log(d) lookup required to
00375      * enforce the adjacency constraint we do not check at this time.
00376      */
00377     virtual const vertex_data_type& 
00378     neighbor_vertex_data(vertex_id_t vertex) const = 0;
00379         
00380 
00381         /**
00382      * \brief get an immutable reference to the data associated with a
00383      * neighboring vertex.
00384      *
00385      * This function should only be invoked on neighboring
00386      * vertices. Unfortunately, due to the Log(d) lookup required to
00387      * enforce the adjacency constraint we do not check at this time.
00388      */
00389     virtual const vertex_data_type& 
00390     const_neighbor_vertex_data(vertex_id_t vertex) const = 0;
00391 
00392 
00393     /**
00394     Experimental scope upgrade scheme. Returns true if scope upgrade is 
00395     successful. If this ever returns false, you are hosed. Should work
00396     with general_scope. Note that after scope_upgrade is called, any graph
00397     data within the scope may change due to a race between releasing and 
00398     reacquiring the upgraded scope.
00399     */
00400     virtual bool 
00401     experimental_scope_upgrade(scope_range::scope_range_enum newrange) { 
00402       return false;
00403     }
00404 
00405   protected:
00406     /** A pointer to the underlying graph datastructure */
00407     Graph* _graph_ptr;
00408 
00409     /** The vertex that this graph represents*/
00410     vertex_id_t _vertex;
00411 
00412   }; // end of iscope
00413   
00414 } // end of namespace
00415 #include <graphlab/macros_undef.hpp>
00416 
00417 #endif
00418