| 269 | } |
| 270 | |
| 271 | CheckResult ReplicatedMergeTreePartCheckThread::checkPart(const String & part_name) |
| 272 | { |
| 273 | LOG_WARNING(log, "Checking part {}", part_name); |
| 274 | ProfileEvents::increment(ProfileEvents::ReplicatedPartChecks); |
| 275 | |
| 276 | auto [exists_in_zookeeper, part] = findLocalPart(part_name); |
| 277 | |
| 278 | LOG_TRACE(log, "Part {} in zookeeper: {}, locally: {}", part_name, exists_in_zookeeper, part != nullptr); |
| 279 | |
| 280 | /// We do not have this or a covering part. |
| 281 | if (!part) |
| 282 | { |
| 283 | searchForMissingPartAndFetchIfPossible(part_name, exists_in_zookeeper); |
| 284 | return {part_name, false, "Part is missing, will search for it"}; |
| 285 | } |
| 286 | |
| 287 | /// We have this part, and it's active. We will check whether we need this part and whether it has the right data. |
| 288 | if (part->name == part_name) |
| 289 | { |
| 290 | auto zookeeper = storage.getZooKeeper(); |
| 291 | auto table_lock = storage.lockForShare(RWLockImpl::NO_QUERY, storage.getSettings()->lock_acquire_timeout_for_background_operations); |
| 292 | |
| 293 | auto local_part_header = ReplicatedMergeTreePartHeader::fromColumnsAndChecksums( |
| 294 | part->getColumns(), *(part->getChecksums())); |
| 295 | |
| 296 | /// The double get scheme is needed to retain compatibility with very old parts that were created |
| 297 | /// before the ReplicatedMergeTreePartHeader was introduced. |
| 298 | |
| 299 | String part_path = storage.replica_path + "/parts/" + part_name; |
| 300 | String part_znode; |
| 301 | /// If the part is in ZooKeeper, check its data with its checksums, and them with ZooKeeper. |
| 302 | if (zookeeper->tryGet(part_path, part_znode)) |
| 303 | { |
| 304 | LOG_WARNING(log, "Checking data of part {}.", part_name); |
| 305 | |
| 306 | try |
| 307 | { |
| 308 | ReplicatedMergeTreePartHeader zk_part_header; |
| 309 | if (!part_znode.empty()) |
| 310 | zk_part_header = ReplicatedMergeTreePartHeader::fromString(part_znode); |
| 311 | else |
| 312 | { |
| 313 | String columns_znode = zookeeper->get(part_path + "/columns"); |
| 314 | String checksums_znode = zookeeper->get(part_path + "/checksums"); |
| 315 | zk_part_header = ReplicatedMergeTreePartHeader::fromColumnsAndChecksumsZNodes( |
| 316 | columns_znode, checksums_znode); |
| 317 | } |
| 318 | |
| 319 | if (local_part_header.getColumnsHash() != zk_part_header.getColumnsHash()) |
| 320 | throw Exception("Columns of local part " + part_name + " are different from ZooKeeper", ErrorCodes::TABLE_DIFFERS_TOO_MUCH); |
| 321 | |
| 322 | zk_part_header.getChecksums().checkEqual(local_part_header.getChecksums(), true); |
| 323 | |
| 324 | checkDataPart( |
| 325 | part, |
| 326 | true, |
| 327 | [this] { return need_stop.load(); }); |
| 328 |
no test coverage detected