From 6488604bcf5cce3126a7631d3bb73acfa15fe7bb Mon Sep 17 00:00:00 2001 From: Nick Ginther Date: Fri, 5 Sep 2025 10:48:37 -0500 Subject: [PATCH 1/8] add blank test --- solrman/smstorage/inmemory_storage.go | 3 ++- solrman/smstorage/inmemory_storage_test.go | 4 ++++ solrman/smstorage/storage_test.go | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/solrman/smstorage/inmemory_storage.go b/solrman/smstorage/inmemory_storage.go index 8aae48c..7bcf170 100644 --- a/solrman/smstorage/inmemory_storage.go +++ b/solrman/smstorage/inmemory_storage.go @@ -33,6 +33,7 @@ type InMemoryStorage struct { queryAggregatorStabbingEnabled bool inProgress map[string]solrmanapi.OpRecord completed []solrmanapi.OpRecord + stationaryOrgList []string } var _ SolrManStorage = &InMemoryStorage{} @@ -98,7 +99,7 @@ func (s *InMemoryStorage) GetStationaryOrgList() ([]string, error) { s.mu.RLock() defer s.mu.RUnlock() - return nil, nil + return s.stationaryOrgList, nil } func (s *InMemoryStorage) IsDisabled() (bool, error) { diff --git a/solrman/smstorage/inmemory_storage_test.go b/solrman/smstorage/inmemory_storage_test.go index 0204670..97d54ad 100644 --- a/solrman/smstorage/inmemory_storage_test.go +++ b/solrman/smstorage/inmemory_storage_test.go @@ -25,3 +25,7 @@ func TestInMemoryStorage_InProgressOps(t *testing.T) { func TestInMemoryStorage_CompletedOps(t *testing.T) { testStorage_CompletedOps(t, &InMemoryStorage{}) } + +func TestInMemoryStorage_StationaryOrgList(t *testing.T) { + testStorage_StationaryOrgList(t, &InMemoryStorage{}) +} diff --git a/solrman/smstorage/storage_test.go b/solrman/smstorage/storage_test.go index 4b37a38..abe8cea 100644 --- a/solrman/smstorage/storage_test.go +++ b/solrman/smstorage/storage_test.go @@ -127,3 +127,7 @@ func testStorage_CompletedOps(t *testing.T, s SolrManStorage) { // A negative count also returns all values. assertOps(-1, expectOps...) } + +func testStorage_StationaryOrgList(t *testing.T, s SolrManStorage) { + +} From 430008626144b167fff5f8901b7ad09e0625318a Mon Sep 17 00:00:00 2001 From: Nick Ginther Date: Fri, 5 Sep 2025 10:51:29 -0500 Subject: [PATCH 2/8] base test --- solrman/smstorage/storage_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/solrman/smstorage/storage_test.go b/solrman/smstorage/storage_test.go index abe8cea..41ee551 100644 --- a/solrman/smstorage/storage_test.go +++ b/solrman/smstorage/storage_test.go @@ -129,5 +129,12 @@ func testStorage_CompletedOps(t *testing.T, s SolrManStorage) { } func testStorage_StationaryOrgList(t *testing.T, s SolrManStorage) { - + stationaryOrgList, err := s.GetStationaryOrgList() + if err != nil { + t.Errorf("GetStationaryOrgList failed: %s", err) + return + } + if len(stationaryOrgList) != 0 { + t.Errorf("expected empty stationary org list, got %v", stationaryOrgList) + } } From 282b2305695525c6c01004bf18d8e8f15951f1f8 Mon Sep 17 00:00:00 2001 From: Nick Ginther Date: Fri, 5 Sep 2025 11:12:18 -0500 Subject: [PATCH 3/8] implement testing versions of add and remove stationary orgs --- solrman/smstorage/inmemory_storage.go | 23 +++++++++++++ solrman/smstorage/storage.go | 2 ++ solrman/smstorage/storage_test.go | 47 +++++++++++++++++++++++++++ solrman/smstorage/zk_storage.go | 8 +++++ 4 files changed, 80 insertions(+) diff --git a/solrman/smstorage/inmemory_storage.go b/solrman/smstorage/inmemory_storage.go index 7bcf170..547a350 100644 --- a/solrman/smstorage/inmemory_storage.go +++ b/solrman/smstorage/inmemory_storage.go @@ -102,6 +102,29 @@ func (s *InMemoryStorage) GetStationaryOrgList() ([]string, error) { return s.stationaryOrgList, nil } +func (s *InMemoryStorage) AddStationaryOrgs(orgs []string) ([]string, error) { + s.mu.RLock() + defer s.mu.RUnlock() + s.stationaryOrgList = append(s.stationaryOrgList, orgs...) + + return s.stationaryOrgList, nil +} + +func (s *InMemoryStorage) RemoveStationaryOrgs(orgs []string) ([]string, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + for _, org := range orgs { + for i, _ := range s.stationaryOrgList { + if s.stationaryOrgList[i] == org { + s.stationaryOrgList = append(s.stationaryOrgList[:i], s.stationaryOrgList[i+1:]...) + break + } + } + } + return s.stationaryOrgList, nil +} + func (s *InMemoryStorage) IsDisabled() (bool, error) { s.mu.RLock() defer s.mu.RUnlock() diff --git a/solrman/smstorage/storage.go b/solrman/smstorage/storage.go index e284e2e..267d4d9 100644 --- a/solrman/smstorage/storage.go +++ b/solrman/smstorage/storage.go @@ -43,6 +43,8 @@ type SolrManStorage interface { // Returns a list of solr orgs that should not be split or moved. GetStationaryOrgList() ([]string, error) + AddStationaryOrgs(orgs []string) ([]string, error) + RemoveStationaryOrgs(orgs []string) ([]string, error) IsDisabled() (bool, error) // if true, solrman is entirely disabled GetDisabledReasons() (map[string]string, error) // diff --git a/solrman/smstorage/storage_test.go b/solrman/smstorage/storage_test.go index 41ee551..57f8990 100644 --- a/solrman/smstorage/storage_test.go +++ b/solrman/smstorage/storage_test.go @@ -137,4 +137,51 @@ func testStorage_StationaryOrgList(t *testing.T, s SolrManStorage) { if len(stationaryOrgList) != 0 { t.Errorf("expected empty stationary org list, got %v", stationaryOrgList) } + + // test adding orgs + orgs := []string{"org1", "org2", "org3"} + stationaryOrgList, err = s.AddStationaryOrgs(orgs) + if err != nil { + t.Errorf("AddStationaryOrgs failed: %s", err) + return + } + if len(orgs) != len(stationaryOrgList) { + t.Errorf("expected %d orgs in stationary org list, got %v", len(orgs), stationaryOrgList) + } + for i := range orgs { + for j := range stationaryOrgList { + if orgs[i] == stationaryOrgList[j] { + break + } + if j == len(stationaryOrgList)-1 { + t.Errorf("expected org %s in stationary org list, got %v", orgs[i], stationaryOrgList) + } + } + } + + orgsToRemove := []string{"org2"} + expectedRemainingOrgs := []string{"org1", "org3"} + stationaryOrgList, err = s.RemoveStationaryOrgs(orgsToRemove) + if err != nil { + t.Errorf("RemoveStationaryOrgs failed: %s", err) + return + } + if len(expectedRemainingOrgs) != len(stationaryOrgList) { + t.Errorf("expected %d orgs in stationary org list, got %v", len(orgs), stationaryOrgList) + } + for _, org := range stationaryOrgList { + if org == "org2" { + t.Errorf("expected org %s not in stationary org list, got %v", org, stationaryOrgList) + } + } + for i := range expectedRemainingOrgs { + for j := range stationaryOrgList { + if expectedRemainingOrgs[i] == stationaryOrgList[j] { + break + } + if j == len(stationaryOrgList)-1 { + t.Errorf("expected org %s in stationary org list, got %v", orgs[i], stationaryOrgList) + } + } + } } diff --git a/solrman/smstorage/zk_storage.go b/solrman/smstorage/zk_storage.go index 5e6bfb0..e5f563e 100644 --- a/solrman/smstorage/zk_storage.go +++ b/solrman/smstorage/zk_storage.go @@ -206,6 +206,14 @@ func (s *ZkStorage) GetStationaryOrgList() ([]string, error) { return children, nil } +func (s *ZkStorage) AddStationaryOrgs(orgs []string) ([]string, error) { + panic("not implemented") +} + +func (s *ZkStorage) RemoveStationaryOrgs(orgs []string) ([]string, error) { + panic("not implemented") +} + func (s *ZkStorage) IsDisabled() (bool, error) { path := s.disabledPath() children, _, err := s.conn.Children(path) From 7d926f6b078518d665f1d24a5c20a3aed7a80d9b Mon Sep 17 00:00:00 2001 From: Nick Ginther Date: Fri, 5 Sep 2025 11:16:55 -0500 Subject: [PATCH 4/8] fix zk tests, add test stub --- solrman/smstorage/zk_storage_test.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/solrman/smstorage/zk_storage_test.go b/solrman/smstorage/zk_storage_test.go index 7cc1a92..5a5659d 100644 --- a/solrman/smstorage/zk_storage_test.go +++ b/solrman/smstorage/zk_storage_test.go @@ -138,10 +138,10 @@ func TestZkStorage_IsDisabled(t *testing.T) { testutil.createWithData(s.disabledPath()+"/test", "testDisabled") - if isDisabled, _ := s.IsDisabled(); !IsDisabled { + if isDisabled, _ := s.IsDisabled(); !isDisabled { t.Error("expected to be disabled") - } else if reasons, _ := s.GetDisabledReasons(); reasons[0] != "testDisabled" { - t.Errorf("expect reason is \"testDisabled\"; got %s", reason) + } else if reasons, _ := s.GetDisabledReasons(); reasons["test"] != "testDisabled" { + t.Errorf("expect reason is \"testDisabled\"; got %s", reasons["test"]) } } @@ -151,7 +151,7 @@ func TestZkStorage_SetDisabled(t *testing.T) { defer testutil.teardown() if isDisabled, reason := s.IsDisabled(); isDisabled { - t.Error("expected to not be disabled; reason found was %s", reason) + t.Errorf("expected to not be disabled; reason found was %s", reason) } if ok, _, _ := s.conn.Exists(s.disabledPath()); ok { t.Errorf("%s should not exist", s.disabledPath()) @@ -233,3 +233,9 @@ func TestZkStorage_IsQueryAggregatorStabbingEnabled(t *testing.T) { t.Error("expected query aggregator stabbing to be enabled") } } + +func TestZkStorage_GetStationaryOrgList(t *testing.T) { + s, testutil := setup(t) + defer testutil.teardown() + testStorage_StationaryOrgList(t, s) +} From 3eb87aefb236732d8ab2c2e53c54ad85d66b948d Mon Sep 17 00:00:00 2001 From: Nick Ginther Date: Fri, 5 Sep 2025 14:42:52 -0500 Subject: [PATCH 5/8] add and remove for ZK storage implementation --- solrman/smstorage/inmemory_storage.go | 7 +++- solrman/smstorage/stationary_org_set.go | 1 + solrman/smstorage/storage_test.go | 12 ++++-- solrman/smstorage/zk_storage.go | 51 ++++++++++++++++++++++++- 4 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 solrman/smstorage/stationary_org_set.go diff --git a/solrman/smstorage/inmemory_storage.go b/solrman/smstorage/inmemory_storage.go index 547a350..3d63fcc 100644 --- a/solrman/smstorage/inmemory_storage.go +++ b/solrman/smstorage/inmemory_storage.go @@ -105,11 +105,16 @@ func (s *InMemoryStorage) GetStationaryOrgList() ([]string, error) { func (s *InMemoryStorage) AddStationaryOrgs(orgs []string) ([]string, error) { s.mu.RLock() defer s.mu.RUnlock() - s.stationaryOrgList = append(s.stationaryOrgList, orgs...) + s.stationaryOrgList = AddOrgsToStationaryOrgList(orgs, s.stationaryOrgList) return s.stationaryOrgList, nil } +func AddOrgsToStationaryOrgList(orgs []string, stationaryOrgList []string) []string { + stationaryOrgList = append(stationaryOrgList, orgs...) + return stationaryOrgList +} + func (s *InMemoryStorage) RemoveStationaryOrgs(orgs []string) ([]string, error) { s.mu.RLock() defer s.mu.RUnlock() diff --git a/solrman/smstorage/stationary_org_set.go b/solrman/smstorage/stationary_org_set.go new file mode 100644 index 0000000..ed18839 --- /dev/null +++ b/solrman/smstorage/stationary_org_set.go @@ -0,0 +1 @@ +package smstorage diff --git a/solrman/smstorage/storage_test.go b/solrman/smstorage/storage_test.go index 57f8990..04a3891 100644 --- a/solrman/smstorage/storage_test.go +++ b/solrman/smstorage/storage_test.go @@ -159,8 +159,8 @@ func testStorage_StationaryOrgList(t *testing.T, s SolrManStorage) { } } - orgsToRemove := []string{"org2"} - expectedRemainingOrgs := []string{"org1", "org3"} + orgsToRemove := []string{"org2", "org3"} + expectedRemainingOrgs := []string{"org1"} stationaryOrgList, err = s.RemoveStationaryOrgs(orgsToRemove) if err != nil { t.Errorf("RemoveStationaryOrgs failed: %s", err) @@ -170,7 +170,7 @@ func testStorage_StationaryOrgList(t *testing.T, s SolrManStorage) { t.Errorf("expected %d orgs in stationary org list, got %v", len(orgs), stationaryOrgList) } for _, org := range stationaryOrgList { - if org == "org2" { + if org == "org2" || org == "org3" { t.Errorf("expected org %s not in stationary org list, got %v", org, stationaryOrgList) } } @@ -184,4 +184,10 @@ func testStorage_StationaryOrgList(t *testing.T, s SolrManStorage) { } } } + + stationaryOrgList, err = s.RemoveStationaryOrgs([]string{"doesnotexist"}) + if err != nil { + t.Errorf("RemoveStationaryOrgs failed: %s", err) + return + } } diff --git a/solrman/smstorage/zk_storage.go b/solrman/smstorage/zk_storage.go index e5f563e..e37c81b 100644 --- a/solrman/smstorage/zk_storage.go +++ b/solrman/smstorage/zk_storage.go @@ -207,11 +207,58 @@ func (s *ZkStorage) GetStationaryOrgList() ([]string, error) { } func (s *ZkStorage) AddStationaryOrgs(orgs []string) ([]string, error) { - panic("not implemented") + path := s.stationaryPath() + children, _, err := s.conn.Children(path) + if err == zk.ErrNoNode { + return nil, nil + } + if err != nil { + return nil, smutil.Cherrf(err, "could not get children at %s in ZK", path) + } + + for _, org := range orgs { + orgPath := fmt.Sprintf("%s/%s", path, org) + _, err = s.conn.Create(orgPath, nil, 0, zk.WorldACL(zk.PermAll)) + if err == zk.ErrNodeExists { + continue + } + if err != nil { + return nil, smutil.Cherrf(err, "could not create %s in ZK", orgPath) + } + } + + children, _, err = s.conn.Children(path) + if err == zk.ErrNoNode { + return nil, nil + } + if err != nil { + return nil, smutil.Cherrf(err, "could not get children at %s in ZK", path) + } + sort.Strings(children) + + return children, nil } func (s *ZkStorage) RemoveStationaryOrgs(orgs []string) ([]string, error) { - panic("not implemented") + path := s.stationaryPath() + for _, org := range orgs { + orgPath := fmt.Sprintf("%s/%s", path, org) + err := s.conn.Delete(orgPath, -1) + if err != nil && err != zk.ErrNoNode { + return nil, smutil.Cherrf(err, "could not delete %s in ZK", orgPath) + } + } + + children, _, err := s.conn.Children(path) + if err == zk.ErrNoNode { + return nil, nil + } + if err != nil { + return nil, smutil.Cherrf(err, "could not get children at %s in ZK", path) + } + sort.Strings(children) + + return children, nil } func (s *ZkStorage) IsDisabled() (bool, error) { From 4448571c28af9f7bd9305b7df250a0b6d7fc65c2 Mon Sep 17 00:00:00 2001 From: Nick Ginther Date: Fri, 5 Sep 2025 14:44:13 -0500 Subject: [PATCH 6/8] remove unused function --- solrman/smstorage/inmemory_storage.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/solrman/smstorage/inmemory_storage.go b/solrman/smstorage/inmemory_storage.go index 3d63fcc..547a350 100644 --- a/solrman/smstorage/inmemory_storage.go +++ b/solrman/smstorage/inmemory_storage.go @@ -105,16 +105,11 @@ func (s *InMemoryStorage) GetStationaryOrgList() ([]string, error) { func (s *InMemoryStorage) AddStationaryOrgs(orgs []string) ([]string, error) { s.mu.RLock() defer s.mu.RUnlock() - s.stationaryOrgList = AddOrgsToStationaryOrgList(orgs, s.stationaryOrgList) + s.stationaryOrgList = append(s.stationaryOrgList, orgs...) return s.stationaryOrgList, nil } -func AddOrgsToStationaryOrgList(orgs []string, stationaryOrgList []string) []string { - stationaryOrgList = append(stationaryOrgList, orgs...) - return stationaryOrgList -} - func (s *InMemoryStorage) RemoveStationaryOrgs(orgs []string) ([]string, error) { s.mu.RLock() defer s.mu.RUnlock() From b0248c61d0b121480f806aca28e05e0f4c785ab7 Mon Sep 17 00:00:00 2001 From: Nick Ginther Date: Fri, 5 Sep 2025 14:44:52 -0500 Subject: [PATCH 7/8] remove unused file --- solrman/smstorage/stationary_org_set.go | 1 - 1 file changed, 1 deletion(-) delete mode 100644 solrman/smstorage/stationary_org_set.go diff --git a/solrman/smstorage/stationary_org_set.go b/solrman/smstorage/stationary_org_set.go deleted file mode 100644 index ed18839..0000000 --- a/solrman/smstorage/stationary_org_set.go +++ /dev/null @@ -1 +0,0 @@ -package smstorage From f215b078ad9c1a62458ea8bc698a49bab7ad73ef Mon Sep 17 00:00:00 2001 From: Nick Ginther Date: Fri, 5 Sep 2025 15:26:33 -0500 Subject: [PATCH 8/8] gofmt --- solrman/smstorage/inmemory_storage.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solrman/smstorage/inmemory_storage.go b/solrman/smstorage/inmemory_storage.go index 547a350..4e88257 100644 --- a/solrman/smstorage/inmemory_storage.go +++ b/solrman/smstorage/inmemory_storage.go @@ -115,7 +115,7 @@ func (s *InMemoryStorage) RemoveStationaryOrgs(orgs []string) ([]string, error) defer s.mu.RUnlock() for _, org := range orgs { - for i, _ := range s.stationaryOrgList { + for i := range s.stationaryOrgList { if s.stationaryOrgList[i] == org { s.stationaryOrgList = append(s.stationaryOrgList[:i], s.stationaryOrgList[i+1:]...) break