This check is to ensure that the two modules, with the same module name, are indeed identical. We verify that they belong to the same module library and have identical attributes such as parameters, kind, version, etc. Notice that this check doesn't prevent one from having multiple instances of the same module. In the current implementation, it is up to the module developer to return an error if
| 211 | // TODO(karya): MESOS-4960: Enhance the module API to allow module developers to |
| 212 | // express whether the modules are multi-instantiable and thread-safe. |
| 213 | Try<Nothing> ModuleManager::verifyIdenticalModule( |
| 214 | const string& libraryName, |
| 215 | const Modules::Library::Module& module, |
| 216 | const ModuleBase* base) |
| 217 | { |
| 218 | const string& moduleName = module.name(); |
| 219 | |
| 220 | // Verify that the two modules come from the same module library. |
| 221 | CHECK(moduleLibraries.contains(moduleName)); |
| 222 | if (libraryName != moduleLibraries[moduleName]) { |
| 223 | return Error( |
| 224 | "The same module appears in two different module libraries - " |
| 225 | "'" + libraryName + "' and '" + moduleLibraries[moduleName] + "'"); |
| 226 | } |
| 227 | |
| 228 | // Verify that the two modules contain the same set of parameters that appear |
| 229 | // in the same order. |
| 230 | CHECK(moduleParameters.contains(moduleName)); |
| 231 | const Parameters& parameters = moduleParameters[moduleName]; |
| 232 | bool parameterError = |
| 233 | module.parameters().size() != parameters.parameter().size(); |
| 234 | |
| 235 | for (int i = 0; i < module.parameters().size() && !parameterError; i++) { |
| 236 | const Parameter& lhs = parameters.parameter().Get(i); |
| 237 | const Parameter& rhs = module.parameters().Get(i); |
| 238 | if (lhs.key() != rhs.key() || lhs.value() != rhs.value()) { |
| 239 | parameterError = true; |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | if (parameterError) { |
| 244 | return Error( |
| 245 | "A module with same name but different parameters already exists"); |
| 246 | } |
| 247 | |
| 248 | // Verify that the two `ModuleBase` definitions match. |
| 249 | CHECK_NOTNULL(base); |
| 250 | CHECK(moduleBases.contains(moduleName)); |
| 251 | ModuleBase* duplicateBase = moduleBases[moduleName]; |
| 252 | |
| 253 | // TODO(karya): MESOS-4918: Cache module manifests to avoid potential |
| 254 | // overwrite of `ModuleBase` fields by the module itself. |
| 255 | if (strcmp(base->moduleApiVersion, duplicateBase->moduleApiVersion) != 0 || |
| 256 | strcmp(base->mesosVersion, duplicateBase->mesosVersion) != 0 || |
| 257 | strcmp(base->kind, duplicateBase->kind) != 0 || |
| 258 | strcmp(base->authorName, duplicateBase->authorName) != 0 || |
| 259 | strcmp(base->authorEmail, duplicateBase->authorEmail) != 0 || |
| 260 | strcmp(base->description, duplicateBase->description) != 0 || |
| 261 | base->compatible != duplicateBase->compatible) { |
| 262 | return Error( |
| 263 | "A module with same name but different module manifest already exists"); |
| 264 | } |
| 265 | |
| 266 | return Nothing(); |
| 267 | } |
| 268 | |
| 269 | |
| 270 | Try<Nothing> ModuleManager::loadManifest(const Modules& modules) |