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
1.7.1