| 178 | } |
| 179 | |
| 180 | Status GraphExecutionState::Extend( |
| 181 | const GraphDef& extension_def, |
| 182 | std::unique_ptr<GraphExecutionState>* out) const { |
| 183 | if (session_options_->config.experimental().optimize_for_static_graph()) { |
| 184 | return errors::FailedPrecondition( |
| 185 | "Extending the graph is not supported when " |
| 186 | "`optimize_for_static_graph` is true."); |
| 187 | } |
| 188 | |
| 189 | GraphDef gdef; |
| 190 | |
| 191 | // 1. Copy the function library. |
| 192 | TF_RETURN_IF_ERROR(flib_def_->AddLibrary(extension_def.library())); |
| 193 | *gdef.mutable_library() = flib_def_->ToProto(); |
| 194 | |
| 195 | // 2. Build an index of the new node names. |
| 196 | std::unordered_set<string> new_names; |
| 197 | for (const NodeDef& node : extension_def.node()) { |
| 198 | new_names.insert(node.name()); |
| 199 | } |
| 200 | |
| 201 | // 3. Add the non-duplicates from the old graph to the new graph. |
| 202 | // Return an error if the same node name appears in both the |
| 203 | // old graph and the extension. |
| 204 | for (const NodeDef& node : original_graph_def_->node()) { |
| 205 | if (new_names.count(node.name()) == 0) { |
| 206 | *gdef.add_node() = node; |
| 207 | } else { |
| 208 | return errors::InvalidArgument( |
| 209 | "GraphDef argument to Extend includes node '", node.name(), |
| 210 | "', which was created by a previous call to Create or Extend in this " |
| 211 | "session."); |
| 212 | } |
| 213 | } |
| 214 | |
| 215 | // 4. Merge the versions field. |
| 216 | int old_node_size = gdef.node_size(); |
| 217 | gdef.mutable_node()->MergeFrom(extension_def.node()); |
| 218 | TF_RETURN_IF_ERROR( |
| 219 | AddDefaultAttrsToGraphDef(&gdef, *flib_def_, old_node_size)); |
| 220 | // Merge versions |
| 221 | if (gdef.has_versions()) { |
| 222 | if (gdef.versions().producer() != extension_def.versions().producer()) { |
| 223 | return errors::InvalidArgument( |
| 224 | "Can't extend GraphDef at version ", gdef.versions().producer(), |
| 225 | " with graph at version ", extension_def.versions().producer()); |
| 226 | } |
| 227 | VersionDef* versions = gdef.mutable_versions(); |
| 228 | versions->set_min_consumer(std::max( |
| 229 | versions->min_consumer(), extension_def.versions().min_consumer())); |
| 230 | if (extension_def.versions().bad_consumers_size()) { |
| 231 | // Add new bad_consumers that aren't already marked bad. |
| 232 | // |
| 233 | // Note: This implementation is quadratic time if there are many calls to |
| 234 | // ExtendLocked with many bad consumers. Since this is unlikely, and |
| 235 | // fixing it would require data structures outside of this routine, |
| 236 | // quadratic time it is. |
| 237 | auto* bad_consumers = versions->mutable_bad_consumers(); |
nothing calls this directly
no test coverage detected