| 2349 | } |
| 2350 | |
| 2351 | bool |
| 2352 | HGraph::UpdateVector(int64_t id, const DatasetPtr& new_base, bool force_update) { |
| 2353 | // check if id exists and get copied base data |
| 2354 | uint32_t inner_id = 0; |
| 2355 | { |
| 2356 | std::shared_lock label_lock(this->label_lookup_mutex_); |
| 2357 | inner_id = this->label_table_->GetIdByLabel(id); |
| 2358 | } |
| 2359 | |
| 2360 | // the validation of the new vector |
| 2361 | void* new_base_vec = nullptr; |
| 2362 | size_t data_size = 0; |
| 2363 | get_vectors(data_type_, dim_, new_base, &new_base_vec, &data_size); |
| 2364 | |
| 2365 | if (not force_update) { |
| 2366 | std::shared_lock label_lock(this->label_lookup_mutex_); |
| 2367 | |
| 2368 | // 1. check whether vectors are same |
| 2369 | Vector<int8_t> base_data(data_size, allocator_); |
| 2370 | GetVectorByInnerId(inner_id, (float*)base_data.data()); |
| 2371 | float old_self_dist = this->CalcDistanceById((float*)base_data.data(), id); |
| 2372 | float self_dist = this->CalcDistanceById((float*)new_base_vec, id); |
| 2373 | if (std::abs(old_self_dist - self_dist) < 1e-3) { |
| 2374 | return true; |
| 2375 | } |
| 2376 | |
| 2377 | // 2. check whether the neighborhood relationship is same |
| 2378 | Vector<InnerIdType> neighbors(allocator_); |
| 2379 | this->bottom_graph_->GetNeighbors(inner_id, neighbors); |
| 2380 | for (auto neighbor_inner_id : neighbors) { |
| 2381 | // don't compare with itself |
| 2382 | if (neighbor_inner_id == inner_id) { |
| 2383 | continue; |
| 2384 | } |
| 2385 | |
| 2386 | float neighbor_dist = 0; |
| 2387 | try { |
| 2388 | neighbor_dist = |
| 2389 | this->CalcDistanceById(static_cast<float*>(new_base_vec), |
| 2390 | this->label_table_->GetLabelById(neighbor_inner_id)); |
| 2391 | } catch (const std::runtime_error& e) { |
| 2392 | // incase that neighbor has been deleted |
| 2393 | continue; |
| 2394 | } |
| 2395 | if (neighbor_dist < self_dist) { |
| 2396 | return false; |
| 2397 | } |
| 2398 | } |
| 2399 | } |
| 2400 | |
| 2401 | // note that only modify vector need to obtain unique lock |
| 2402 | // and the lock has been obtained inside datacell |
| 2403 | auto codes = (use_reorder_) ? high_precise_codes_ : basic_flatten_codes_; |
| 2404 | bool update_status = basic_flatten_codes_->UpdateVector(new_base_vec, inner_id); |
| 2405 | if (use_reorder_) { |
| 2406 | update_status = update_status && high_precise_codes_->UpdateVector(new_base_vec, inner_id); |
| 2407 | } |
| 2408 | return update_status; |
no test coverage detected