github.com/polarismesh/polaris@v1.17.8/store/boltdb/instance.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package boltdb 19 20 import ( 21 "errors" 22 "fmt" 23 "sort" 24 "strconv" 25 "strings" 26 "time" 27 28 "github.com/golang/protobuf/ptypes/wrappers" 29 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 30 bolt "go.etcd.io/bbolt" 31 "google.golang.org/protobuf/types/known/wrapperspb" 32 33 "github.com/polarismesh/polaris/common/model" 34 commontime "github.com/polarismesh/polaris/common/time" 35 "github.com/polarismesh/polaris/common/utils" 36 "github.com/polarismesh/polaris/store" 37 ) 38 39 type instanceStore struct { 40 handler BoltHandler 41 } 42 43 const ( 44 tblNameInstance = "instance" 45 insFieldProto = "Proto" 46 insFieldServiceID = "ServiceID" 47 insFieldModifyTime = "ModifyTime" 48 insFieldValid = "Valid" 49 ) 50 51 // AddInstance add an instance 52 func (i *instanceStore) AddInstance(instance *model.Instance) error { 53 initInstance([]*model.Instance{instance}) 54 // Before adding new data, you must clean up the old data 55 if err := i.handler.DeleteValues(tblNameInstance, []string{instance.ID()}); err != nil { 56 log.Errorf("[Store][boltdb] delete instance to kv error, %v", err) 57 return err 58 } 59 60 if err := i.handler.SaveValue(tblNameInstance, instance.ID(), instance); err != nil { 61 log.Errorf("[Store][boltdb] save instance to kv error, %v", err) 62 return err 63 } 64 65 return nil 66 } 67 68 // BatchAddInstances Add multiple instances 69 func (i *instanceStore) BatchAddInstances(instances []*model.Instance) error { 70 71 if len(instances) == 0 { 72 return nil 73 } 74 75 var insIds []string 76 for _, instance := range instances { 77 insIds = append(insIds, instance.ID()) 78 } 79 80 // clear old instances 81 if err := i.handler.DeleteValues(tblNameInstance, insIds); err != nil { 82 log.Errorf("[Store][boltdb] save instance to kv error, %v", err) 83 return err 84 } 85 86 initInstance(instances) 87 for _, instance := range instances { 88 if err := i.handler.SaveValue(tblNameInstance, instance.ID(), instance); err != nil { 89 log.Errorf("[Store][boltdb] save instance to kv error, %v", err) 90 return err 91 } 92 } 93 94 return nil 95 } 96 97 // UpdateInstance Update instance 98 func (i *instanceStore) UpdateInstance(instance *model.Instance) error { 99 100 properties := make(map[string]interface{}) 101 properties[insFieldProto] = instance.Proto 102 curr := time.Now() 103 properties[insFieldModifyTime] = curr 104 instance.Proto.Mtime = &wrappers.StringValue{Value: commontime.Time2String(curr)} 105 106 if err := i.handler.UpdateValue(tblNameInstance, instance.ID(), properties); err != nil { 107 log.Errorf("[Store][boltdb] update instance to kv error, %v", err) 108 return err 109 } 110 111 return nil 112 } 113 114 // DeleteInstance Delete an instance 115 func (i *instanceStore) DeleteInstance(instanceID string) error { 116 117 properties := make(map[string]interface{}) 118 properties[insFieldValid] = false 119 properties[insFieldModifyTime] = time.Now() 120 121 if err := i.handler.UpdateValue(tblNameInstance, instanceID, properties); err != nil { 122 log.Errorf("[Store][boltdb] delete instance from kv error, %v", err) 123 return err 124 } 125 126 return nil 127 } 128 129 // BatchDeleteInstances Delete instances in batch 130 func (i *instanceStore) BatchDeleteInstances(ids []interface{}) error { 131 132 if len(ids) == 0 { 133 return nil 134 } 135 136 for _, id := range ids { 137 138 properties := make(map[string]interface{}) 139 properties[insFieldValid] = false 140 properties[insFieldModifyTime] = time.Now() 141 142 if err := i.handler.UpdateValue(tblNameInstance, id.(string), properties); err != nil { 143 log.Errorf("[Store][boltdb] batch delete instance from kv error, %v", err) 144 return err 145 } 146 } 147 return nil 148 } 149 150 // CleanInstance Delete an instance 151 func (i *instanceStore) CleanInstance(instanceID string) error { 152 if err := i.handler.DeleteValues(tblNameInstance, []string{instanceID}); err != nil { 153 log.Errorf("[Store][boltdb] delete instance from kv error, %v", err) 154 return err 155 } 156 return nil 157 } 158 159 // BatchGetInstanceIsolate Check whether the ID exists, and return the query results of all IDs 160 func (i *instanceStore) BatchGetInstanceIsolate(ids map[string]bool) (map[string]bool, error) { 161 162 if len(ids) == 0 { 163 return nil, nil 164 } 165 166 keys := make([]string, len(ids)) 167 pos := 0 168 for k := range ids { 169 keys[pos] = k 170 pos++ 171 } 172 173 result, err := i.handler.LoadValues(tblNameInstance, keys, &model.Instance{}) 174 if err != nil { 175 log.Errorf("[Store][boltdb] list instance in kv error, %v", err) 176 return nil, err 177 } 178 179 if len(result) == 0 { 180 return ids, nil 181 } 182 183 for id, val := range result { 184 ins := val.(*model.Instance) 185 if !ins.Valid { 186 continue 187 } 188 189 ids[id] = ins.Proto.GetIsolate().GetValue() 190 } 191 192 return ids, nil 193 } 194 195 // GetInstancesBrief Get the token associated with the instance 196 func (i *instanceStore) GetInstancesBrief(ids map[string]bool) (map[string]*model.Instance, error) { 197 198 if len(ids) == 0 { 199 return nil, nil 200 } 201 202 fields := []string{insFieldProto, insFieldValid} 203 204 // find all instances with given ids 205 inss, err := i.handler.LoadValuesByFilter(tblNameInstance, fields, &model.Instance{}, 206 func(m map[string]interface{}) bool { 207 valid, ok := m[insFieldValid] 208 if ok && !valid.(bool) { 209 return false 210 } 211 212 insProto, ok := m[insFieldProto] 213 if !ok { 214 return false 215 } 216 id := insProto.(*apiservice.Instance).GetId().GetValue() 217 _, ok = ids[id] 218 return ok 219 }) 220 if err != nil { 221 log.Errorf("[Store][boltdb] load instance error, %v", err) 222 return nil, err 223 } 224 225 // find the service corresponding to the instance and get the serviceToken 226 serviceIDs := make(map[string]bool) 227 for _, ins := range inss { 228 serviceID := ins.(*model.Instance).ServiceID 229 serviceIDs[serviceID] = true 230 } 231 232 fields = []string{SvcFieldID, SvcFieldValid} 233 services, err := i.handler.LoadValuesByFilter(tblNameService, fields, &model.Service{}, 234 func(m map[string]interface{}) bool { 235 valid, ok := m[insFieldValid] 236 if ok && !valid.(bool) { 237 return false 238 } 239 240 svcId, ok := m[SvcFieldID] 241 if !ok { 242 return false 243 } 244 id := svcId.(string) 245 _, ok = serviceIDs[id] 246 return ok 247 }) 248 249 // assemble return data 250 out := make(map[string]*model.Instance, len(ids)) 251 var item model.ExpandInstanceStore 252 var instance model.InstanceStore 253 item.ServiceInstance = &instance 254 255 for _, ins := range inss { 256 tempIns := ins.(*model.Instance) 257 svc, ok := services[tempIns.ServiceID] 258 if !ok { 259 log.Errorf("[Store][boltdb] can not find instance service , instanceId is %s", tempIns.ID()) 260 return nil, errors.New("can not find instance service") 261 } 262 tempService := svc.(*model.Service) 263 instance.ID = tempIns.ID() 264 instance.Host = tempIns.Host() 265 instance.Port = tempIns.Port() 266 item.ServiceName = tempService.Name 267 item.Namespace = tempService.Namespace 268 item.ServiceToken = tempService.Token 269 item.ServicePlatformID = tempService.PlatformID 270 271 out[instance.ID] = model.ExpandStore2Instance(&item) 272 } 273 274 return out, nil 275 } 276 277 // GetInstance Query the details of an instance 278 func (i *instanceStore) GetInstance(instanceID string) (*model.Instance, error) { 279 fields := []string{insFieldProto, insFieldValid} 280 ins, err := i.handler.LoadValuesByFilter(tblNameInstance, fields, &model.Instance{}, 281 func(m map[string]interface{}) bool { 282 if insValid, _ := m[insFieldValid].(bool); !insValid { 283 return false 284 } 285 insProto, ok := m[insFieldProto] 286 if !ok { 287 return false 288 } 289 id := insProto.(*apiservice.Instance).GetId().GetValue() 290 return id == instanceID 291 }) 292 if err != nil { 293 log.Errorf("[Store][boltdb] load instance from kv error, %v", err) 294 return nil, err 295 } 296 instance, ok := ins[instanceID] 297 if !ok { 298 return nil, nil 299 } 300 return instance.(*model.Instance), nil 301 } 302 303 // GetInstancesCount Get the total number of instances 304 func (i *instanceStore) GetInstancesCount() (uint32, error) { 305 306 count, err := i.handler.CountValues(tblNameInstance) 307 if err != nil { 308 log.Errorf("[Store][boltdb] get instance count error, %v", err) 309 return 0, err 310 } 311 312 return uint32(count), nil 313 } 314 315 // GetInstancesCountTx Get the total number of instances 316 func (i *instanceStore) GetInstancesCountTx(tx store.Tx) (uint32, error) { 317 dbTx, _ := tx.GetDelegateTx().(*bolt.Tx) 318 count, err := countValues(dbTx, tblNameInstance) 319 if err != nil { 320 log.Errorf("[Store][boltdb] get instance count error, %v", err) 321 return 0, err 322 } 323 324 return uint32(count), nil 325 } 326 327 // GetInstancesMainByService Get instances based on service and Host 328 func (i *instanceStore) GetInstancesMainByService(serviceID, host string) ([]*model.Instance, error) { 329 330 // select by service_id and host 331 fields := []string{insFieldServiceID, insFieldProto, insFieldValid} 332 333 instances, err := i.handler.LoadValuesByFilter(tblNameInstance, fields, &model.Instance{}, 334 func(m map[string]interface{}) bool { 335 valid, ok := m[insFieldValid] 336 if ok && !valid.(bool) { 337 return false 338 } 339 340 sId, ok := m[insFieldServiceID] 341 if !ok { 342 return false 343 } 344 insProto, ok := m[insFieldProto] 345 if !ok { 346 return false 347 } 348 349 svcId := sId.(string) 350 h := insProto.(*apiservice.Instance).GetHost().GetValue() 351 if svcId != serviceID { 352 return false 353 } 354 if h != host { 355 return false 356 } 357 return true 358 }) 359 if err != nil { 360 log.Errorf("[Store][boltdb] load instance from kv error, %v", err) 361 return nil, err 362 } 363 364 return getRealInstancesList(instances, 0, uint32(len(instances))), nil 365 } 366 367 // GetExpandInstances View instance details and corresponding number according to filter conditions 368 func (i *instanceStore) GetExpandInstances(filter, metaFilter map[string]string, 369 offset uint32, limit uint32) (uint32, []*model.Instance, error) { 370 if limit == 0 { 371 return 0, make([]*model.Instance, 0), nil 372 } 373 374 // find service 375 name, isServiceName := filter["name"] 376 namespace, isNamespace := filter["namespace"] 377 378 svcIDFilterSet := make(map[string]struct{}, 0) 379 if isNamespace || isServiceName { 380 sStore := serviceStore{handler: i.handler} 381 svcs, err := sStore.GetServiceByNameAndNamespace(name, namespace) 382 if err != nil { 383 log.Errorf("[Store][boltdb] find service error, %v", err) 384 return 0, nil, err 385 } 386 for _, svc := range svcs { 387 svcIDFilterSet[svc.ID] = struct{}{} 388 } 389 if len(svcIDFilterSet) == 0 { 390 return 0, make([]*model.Instance, 0), nil 391 } 392 } 393 394 svcIdsTmp := make(map[string]struct{}) 395 fields := []string{insFieldProto, insFieldServiceID, insFieldValid} 396 397 instances, err := i.handler.LoadValuesByFilter(tblNameInstance, fields, &model.Instance{}, 398 func(m map[string]interface{}) bool { 399 valid, ok := m[insFieldValid] 400 if ok && !valid.(bool) { 401 return false 402 } 403 404 insProto, ok := m[insFieldProto] 405 if !ok { 406 return false 407 } 408 ins := insProto.(*apiservice.Instance) 409 host, isHost := filter["host"] 410 port, isPort := filter["port"] 411 protocol, isProtocol := filter["protocol"] 412 version, isVersion := filter["version"] 413 healthy, isHealthy := filter["health_status"] 414 isolate, isIsolate := filter["isolate"] 415 id, isId := filter["id"] 416 417 if isId { 418 if utils.IsWildName(id) { 419 if !utils.IsWildMatch(ins.GetId().GetValue(), id) { 420 return false 421 } 422 } else { 423 if id != ins.GetId().GetValue() { 424 return false 425 } 426 } 427 } 428 if isHost && host != ins.GetHost().GetValue() { 429 return false 430 } 431 if isPort && port != strconv.Itoa(int(ins.GetPort().GetValue())) { 432 return false 433 } 434 if isProtocol && protocol != ins.GetProtocol().GetValue() { 435 return false 436 } 437 if isVersion && version != ins.GetVersion().GetValue() { 438 return false 439 } 440 if isHealthy && compareParam2BoolNotEqual(healthy, ins.GetHealthy().GetValue()) { 441 return false 442 } 443 if isIsolate && compareParam2BoolNotEqual(isolate, ins.GetIsolate().GetValue()) { 444 return false 445 } 446 447 // 如果提供了 serviceName 或者 namespaceName 才过滤 serviceID 448 if isServiceName || isNamespace { 449 // filter serviceID 450 sID, ok := m["ServiceID"] 451 if !ok { 452 return false 453 } 454 sIDStr, strOK := sID.(string) 455 if !strOK { 456 return false 457 } 458 if _, ok := svcIDFilterSet[sIDStr]; !ok { 459 return false 460 } 461 } 462 463 // filter metadata 464 if len(metaFilter) > 0 { 465 var key, value string 466 for k, v := range metaFilter { 467 key = k 468 value = v 469 break 470 } 471 472 insV, ok := ins.GetMetadata()[key] 473 if !ok || insV != value { 474 return false 475 } 476 } 477 svcIdsTmp[m["ServiceID"].(string)] = struct{}{} 478 return true 479 }) 480 if err != nil { 481 log.Errorf("[Store][boltdb] load instance from kv error, %v", err) 482 return 0, nil, err 483 } 484 485 svcIds := make([]string, len(svcIdsTmp)) 486 pos := 0 487 for k := range svcIdsTmp { 488 svcIds[pos] = k 489 pos++ 490 } 491 svcRets, err := i.handler.LoadValues(tblNameService, svcIds, &model.Service{}) 492 svcRets, err = i.handler.LoadValuesAll(tblNameService, &model.Service{}) 493 if err != nil { 494 log.Errorf("[Store][boltdb] load service from kv error, %v", err) 495 return 0, nil, err 496 } 497 for _, v := range instances { 498 ins := v.(*model.Instance) 499 service, ok := svcRets[ins.ServiceID] 500 if !ok { 501 log.Errorf("[Store][boltdb] no found instance relate service, "+ 502 "instance-id: %s, service-id: %s", ins.ID(), ins.ServiceID) 503 return 0, nil, errors.New("no found instance relate service") 504 } 505 ins.Proto.Service = wrapperspb.String(service.(*model.Service).Name) 506 ins.Proto.Namespace = wrapperspb.String(service.(*model.Service).Namespace) 507 } 508 509 totalCount := uint32(len(instances)) 510 511 return totalCount, getRealInstancesList(instances, offset, limit), nil 512 } 513 514 // GetMoreInstances Get incremental instances according to mtime 515 func (i *instanceStore) GetMoreInstances(tx store.Tx, mtime time.Time, firstUpdate, needMeta bool, 516 serviceID []string) (map[string]*model.Instance, error) { 517 518 dbTx, _ := tx.GetDelegateTx().(*bolt.Tx) 519 520 fields := []string{insFieldProto, insFieldServiceID, insFieldValid} 521 svcIdMap := make(map[string]bool) 522 for _, s := range serviceID { 523 svcIdMap[s] = true 524 } 525 526 instances := make(map[string]interface{}) 527 err := loadValuesByFilter(dbTx, tblNameInstance, fields, &model.Instance{}, 528 func(m map[string]interface{}) bool { 529 530 if firstUpdate { 531 valid, ok := m[insFieldValid] 532 if ok && !valid.(bool) { 533 return false 534 } 535 } 536 537 insProto, ok := m[insFieldProto] 538 if !ok { 539 return false 540 } 541 svcId, ok := m[insFieldServiceID] 542 if !ok { 543 return false 544 } 545 ins := insProto.(*apiservice.Instance) 546 serviceId := svcId.(string) 547 548 insMtime, err := time.Parse("2006-01-02 15:04:05", ins.GetMtime().GetValue()) 549 if err != nil { 550 log.Errorf("[Store][boltdb] parse instance mtime error, %v", err) 551 return false 552 } 553 554 if insMtime.Before(mtime) { 555 return false 556 } 557 558 if len(svcIdMap) > 0 { 559 _, ok = svcIdMap[serviceId] 560 if !ok { 561 return false 562 } 563 } 564 565 return true 566 }, instances) 567 568 if err != nil { 569 log.Errorf("[Store][boltdb] load instance from kv error, %v", err) 570 return nil, err 571 } 572 573 return toInstance(instances), nil 574 } 575 576 // BatchSetInstanceHealthStatus 批量设置实例的健康状态 577 func (i *instanceStore) BatchSetInstanceHealthStatus(ids []interface{}, healthy int, revision string) error { 578 for _, id := range ids { 579 if err := i.SetInstanceHealthStatus(id.(string), healthy, revision); err != nil { 580 return err 581 } 582 } 583 return nil 584 } 585 586 // SetInstanceHealthStatus Set the health status of the instance 587 func (i *instanceStore) SetInstanceHealthStatus(instanceID string, flag int, revision string) error { 588 589 // get instance 590 fields := []string{insFieldProto} 591 592 instances, err := i.handler.LoadValuesByFilter(tblNameInstance, fields, &model.Instance{}, 593 func(m map[string]interface{}) bool { 594 insProto, ok := m[insFieldProto] 595 if !ok { 596 return false 597 } 598 insId := insProto.(*apiservice.Instance).GetId().GetValue() 599 600 return insId == instanceID 601 }) 602 if err != nil { 603 log.Errorf("[Store][boltdb] load instance from kv error, %v", err) 604 return err 605 } 606 if len(instances) == 0 { 607 msg := fmt.Sprintf("cant not find instance in kv, %s", instanceID) 608 log.Errorf(msg) 609 return nil 610 } 611 612 // set status 613 ins := instances[instanceID].(*model.Instance) 614 var healthy bool 615 if flag == 0 { 616 healthy = false 617 } else { 618 healthy = true 619 } 620 ins.Proto.Healthy.Value = healthy 621 ins.Proto.Revision.Value = revision 622 623 properties := make(map[string]interface{}) 624 properties[insFieldProto] = ins.Proto 625 curr := time.Now() 626 properties[insFieldModifyTime] = curr 627 ins.Proto.Mtime = &wrappers.StringValue{Value: commontime.Time2String(curr)} 628 629 err = i.handler.UpdateValue(tblNameInstance, instanceID, properties) 630 if err != nil { 631 log.Errorf("[Store][boltdb] update instance error %v", err) 632 return err 633 } 634 635 return nil 636 } 637 638 // BatchSetInstanceIsolate Modify the isolation status of instances in batches 639 func (i *instanceStore) BatchSetInstanceIsolate(ids []interface{}, isolate int, revision string) error { 640 641 insIds := make(map[string]bool) 642 for _, id := range ids { 643 insIds[id.(string)] = true 644 } 645 var isolateStatus bool 646 if isolate == 0 { 647 isolateStatus = false 648 } else { 649 isolateStatus = true 650 } 651 652 fields := []string{insFieldProto} 653 654 // get all instances by given ids 655 instances, err := i.handler.LoadValuesByFilter(tblNameInstance, fields, &model.Instance{}, 656 func(m map[string]interface{}) bool { 657 proto, ok := m[insFieldProto] 658 if !ok { 659 return false 660 } 661 insId := proto.(*apiservice.Instance).GetId().GetValue() 662 663 _, ok = insIds[insId] 664 return ok 665 }) 666 if err != nil { 667 log.Errorf("[Store][boltdb] get instance from kv error, %v", err) 668 return err 669 } 670 if len(instances) == 0 { 671 msg := fmt.Sprintf("cant not find instance in kv, %v", ids) 672 log.Errorf(msg) 673 return nil 674 } 675 676 for id, ins := range instances { 677 instance := ins.(*model.Instance).Proto 678 instance.Isolate.Value = isolateStatus 679 instance.Revision.Value = revision 680 681 properties := make(map[string]interface{}) 682 properties[insFieldProto] = instance 683 curr := time.Now() 684 properties[insFieldModifyTime] = curr 685 instance.Mtime = &wrappers.StringValue{Value: commontime.Time2String(curr)} 686 err = i.handler.UpdateValue(tblNameInstance, id, properties) 687 if err != nil { 688 log.Errorf("[Store][boltdb] update instance in set instance isolate error, %v", err) 689 return err 690 } 691 } 692 693 return nil 694 } 695 696 // BatchAppendInstanceMetadata 追加实例 metadata 697 func (i *instanceStore) BatchAppendInstanceMetadata(requests []*store.InstanceMetadataRequest) error { 698 if len(requests) == 0 { 699 return nil 700 } 701 return i.handler.Execute(true, func(tx *bolt.Tx) error { 702 values := map[string]interface{}{} 703 fields := []string{insFieldProto, insFieldValid} 704 if err := loadValuesByFilter(tx, tblNameInstance, fields, &model.Instance{}, 705 func(m map[string]interface{}) bool { 706 valid, ok := m[insFieldValid] 707 if ok && !valid.(bool) { 708 return false 709 } 710 proto, ok := m[insFieldProto] 711 if !ok { 712 return false 713 } 714 insId := proto.(*apiservice.Instance).GetId().GetValue() 715 for i := range requests { 716 if requests[i].InstanceID == insId { 717 return true 718 } 719 } 720 return false 721 }, values); err != nil { 722 log.Errorf("[Store][boltdb] do batch append InstanceMetadata get instances error, %v", err) 723 return err 724 } 725 if len(values) == 0 { 726 return nil 727 } 728 for i := range requests { 729 instanceID := requests[i].InstanceID 730 val, ok := values[instanceID] 731 if !ok { 732 return nil 733 } 734 ins := val.(*model.Instance) 735 if len(ins.Proto.GetMetadata()) == 0 { 736 ins.Proto.Metadata = map[string]string{} 737 } 738 for k, v := range requests[i].Metadata { 739 ins.Proto.Metadata[k] = v 740 } 741 properties := make(map[string]interface{}) 742 properties[insFieldProto] = ins.Proto 743 properties[CommonFieldRevision] = requests[i].Revision 744 properties[insFieldModifyTime] = time.Now() 745 if err := updateValue(tx, tblNameInstance, instanceID, properties); err != nil { 746 log.Errorf("[Store][boltdb] do batch append InstanceMetadata update instance by %s error, %v", 747 instanceID, err) 748 return err 749 } 750 } 751 return nil 752 }) 753 } 754 755 // BatchRemoveInstanceMetadata 删除实例指定的 metadata 756 func (i *instanceStore) BatchRemoveInstanceMetadata(requests []*store.InstanceMetadataRequest) error { 757 if len(requests) == 0 { 758 return nil 759 } 760 return i.handler.Execute(true, func(tx *bolt.Tx) error { 761 values := map[string]interface{}{} 762 fields := []string{insFieldProto, insFieldValid} 763 if err := loadValuesByFilter(tx, tblNameInstance, fields, &model.Instance{}, 764 func(m map[string]interface{}) bool { 765 valid, ok := m[insFieldValid] 766 if ok && !valid.(bool) { 767 return false 768 } 769 proto, ok := m[insFieldProto] 770 if !ok { 771 return false 772 } 773 insId := proto.(*apiservice.Instance).GetId().GetValue() 774 for i := range requests { 775 if requests[i].InstanceID == insId { 776 return true 777 } 778 } 779 return false 780 }, values); err != nil { 781 log.Errorf("[Store][boltdb] do batch remove InstanceMetadata get instances error, %v", err) 782 return err 783 } 784 if len(values) == 0 { 785 return nil 786 } 787 for i := range requests { 788 instanceID := requests[i].InstanceID 789 val, ok := values[instanceID] 790 if !ok { 791 continue 792 } 793 ins := val.(*model.Instance) 794 if len(ins.Proto.GetMetadata()) == 0 { 795 ins.Proto.Metadata = map[string]string{} 796 } 797 for p := range requests[i].Keys { 798 delete(ins.Proto.Metadata, requests[i].Keys[p]) 799 } 800 properties := make(map[string]interface{}) 801 properties[insFieldProto] = ins.Proto 802 properties[CommonFieldRevision] = requests[i].Revision 803 properties[insFieldModifyTime] = time.Now() 804 if err := updateValue(tx, tblNameInstance, instanceID, properties); err != nil { 805 log.Errorf("[Store][boltdb] do batch remove InstanceMetadata update instance by %s error, %v", 806 instanceID, err) 807 return err 808 } 809 } 810 return nil 811 }) 812 } 813 814 func toInstance(m map[string]interface{}) map[string]*model.Instance { 815 insMap := make(map[string]*model.Instance) 816 for k, v := range m { 817 insMap[k] = v.(*model.Instance) 818 } 819 820 return insMap 821 } 822 823 func getRealInstancesList(originServices map[string]interface{}, offset, limit uint32) []*model.Instance { 824 instances := make([]*model.Instance, 0) 825 beginIndex := offset 826 endIndex := beginIndex + limit 827 totalCount := uint32(len(originServices)) 828 // handle invalid limit offset 829 if totalCount == 0 { 830 return instances 831 } 832 if beginIndex >= endIndex { 833 return instances 834 } 835 if beginIndex >= totalCount { 836 return instances 837 } 838 if endIndex > totalCount { 839 endIndex = totalCount 840 } 841 842 for _, s := range originServices { 843 instances = append(instances, s.(*model.Instance)) 844 } 845 846 sort.Slice(instances, func(i, j int) bool { 847 // sort by modify time 848 if instances[i].ModifyTime.After(instances[j].ModifyTime) { 849 return true 850 } else if instances[i].ModifyTime.Before(instances[j].ModifyTime) { 851 return false 852 } else { 853 return strings.Compare(instances[i].ID(), instances[j].ID()) < 0 854 } 855 }) 856 857 return instances[beginIndex:endIndex] 858 } 859 860 func initInstance(instance []*model.Instance) { 861 862 if len(instance) == 0 { 863 return 864 } 865 866 for _, ins := range instance { 867 if ins != nil { 868 currT := time.Now() 869 timeStamp := commontime.Time2String(currT) 870 if ins.Proto != nil { 871 if ins.Proto.GetMtime().GetValue() == "" { 872 ins.Proto.Mtime = &wrappers.StringValue{Value: timeStamp} 873 } 874 if ins.Proto.GetCtime().GetValue() == "" { 875 ins.Proto.Ctime = &wrappers.StringValue{Value: timeStamp} 876 } 877 } 878 ins.Valid = true 879 ins.ModifyTime = currT 880 } 881 } 882 } 883 884 func compareParam2BoolNotEqual(param string, b bool) bool { 885 if param == "0" && !b { 886 return false 887 } 888 if param == "1" && b { 889 return false 890 } 891 return true 892 }