From b41ae0ae1a3416def55c0318f39731580db32e4d Mon Sep 17 00:00:00 2001 From: Annika Hannig Date: Fri, 18 Mar 2022 11:04:52 +0100 Subject: [PATCH] use per RS table --- pkg/store/backends/postgres/routes_backend.go | 81 +++++++++++++++---- .../backends/postgres/routes_backend_test.go | 27 ++++++- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/pkg/store/backends/postgres/routes_backend.go b/pkg/store/backends/postgres/routes_backend.go index 71f84d3..b08ad1d 100644 --- a/pkg/store/backends/postgres/routes_backend.go +++ b/pkg/store/backends/postgres/routes_backend.go @@ -7,20 +7,27 @@ import ( "time" "github.com/alice-lg/alice-lg/pkg/api" + "github.com/alice-lg/alice-lg/pkg/config" + "github.com/jackc/pgx/v4" "github.com/jackc/pgx/v4/pgxpool" ) // RoutesBackend implements a postgres store for routes. type RoutesBackend struct { - pool *pgxpool.Pool + pool *pgxpool.Pool + sources []*config.SourceConfig } // NewRoutesBackend creates a new instance with a postgres // connection pool. -func NewRoutesBackend(pool *pgxpool.Pool) *RoutesBackend { +func NewRoutesBackend( + pool *pgxpool.Pool, + sources []*config.SourceConfig, +) *RoutesBackend { return &RoutesBackend{ - pool: pool, + pool: pool, + sources: sources, } } @@ -42,9 +49,11 @@ func (b *RoutesBackend) SetRoutes( } defer tx.Rollback(ctx) - if err := b.clear(ctx, tx, sourceID); err != nil { + // Create table from template + if err := b.initTable(ctx, tx, sourceID); err != nil { return err } + // persist all routes for _, r := range routes { if err := b.persist(ctx, tx, sourceID, r, now); err != nil { @@ -58,6 +67,28 @@ func (b *RoutesBackend) SetRoutes( return nil } +// Private routesTable returns the name of the routes table +// for a sourceID +func (b *RoutesBackend) routesTable(sourceID string) string { + return "routes_" + sourceID +} + +// Private initTable recreates the routes table +// for a single sourceID +func (b *RoutesBackend) initTable( + ctx context.Context, + tx pgx.Tx, + sourceID string, +) error { + tbl := b.routesTable(sourceID) + qry := ` + DROP TABLE IF EXISTS ` + tbl + `; + CREATE TABLE ` + tbl + ` ( LIKE routes INCLUDING ALL ) + ` + _, err := tx.Exec(ctx, qry) + return err +} + // Private persist route in database func (b *RoutesBackend) persist( ctx context.Context, @@ -66,8 +97,9 @@ func (b *RoutesBackend) persist( route *api.LookupRoute, now time.Time, ) error { + tbl := b.routesTable(sourceID) qry := ` - INSERT INTO routes ( + INSERT INTO ` + tbl + ` ( id, rs_id, neighbor_id, @@ -91,17 +123,19 @@ func (b *RoutesBackend) persist( } // Private clear removes all routes. +/* func (b *RoutesBackend) clear( ctx context.Context, tx pgx.Tx, sourceID string, ) error { qry := ` - DELETE FROM routes WHERE rs_id = $1 + DELETE FROM routes WHERE rs_id = $1 ` _, err := tx.Exec(ctx, qry, sourceID) return err } +*/ // Private queryCountByState will query routes and filter // by state @@ -111,10 +145,11 @@ func (b *RoutesBackend) queryCountByState( sourceID string, state string, ) pgx.Row { - qry := `SELECT COUNT(1) FROM routes - WHERE rs_id = $1 AND route -> 'state' = $2` + tbl := b.routesTable(sourceID) + qry := `SELECT COUNT(1) FROM ` + tbl + ` + WHERE route -> 'state' = $1` - return tx.QueryRow(ctx, qry, sourceID, "\""+state+"\"") + return tx.QueryRow(ctx, qry, "\""+state+"\"") } // CountRoutesAt returns the number of filtered and imported @@ -171,9 +206,17 @@ func (b *RoutesBackend) FindByNeighbors( vars[i] = fmt.Sprintf("$%d", i+1) } listQry := strings.Join(vars, ",") - qry := ` - SELECT route FROM routes - WHERE neighbor_id IN (` + listQry + `)` + + qrys := []string{} + for _, src := range b.sources { + tbl := b.routesTable(src.ID) + qry := ` + SELECT route FROM ` + tbl + ` + WHERE neighbor_id IN (` + listQry + `)` + qrys = append(qrys, qry) + } + + qry := strings.Join(qrys, " UNION ") rows, err := tx.Query(ctx, qry, vals...) if err != nil { @@ -196,10 +239,16 @@ func (b *RoutesBackend) FindByPrefix( } defer tx.Rollback(ctx) // We are searching route.Network - qry := ` - SELECT route FROM routes - WHERE network ILIKE $1 - ` + qrys := []string{} + for _, src := range b.sources { + tbl := b.routesTable(src.ID) + qry := ` + SELECT route FROM ` + tbl + ` + WHERE network ILIKE $1 + ` + qrys = append(qrys, qry) + } + qry := strings.Join(qrys, " UNION ") rows, err := tx.Query(ctx, qry, prefix+"%") if err != nil { return nil, err diff --git a/pkg/store/backends/postgres/routes_backend_test.go b/pkg/store/backends/postgres/routes_backend_test.go index fd8a0c5..6e88456 100644 --- a/pkg/store/backends/postgres/routes_backend_test.go +++ b/pkg/store/backends/postgres/routes_backend_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/alice-lg/alice-lg/pkg/api" + "github.com/alice-lg/alice-lg/pkg/config" ) func TestCountRoutesAt(t *testing.T) { @@ -29,6 +30,7 @@ func TestCountRoutesAt(t *testing.T) { Network: "1.2.3.0/24", }, } + b.initTable(ctx, tx, "rs1") b.persist(ctx, tx, "rs1", r, now) r.Route.ID = "r4242" @@ -63,7 +65,13 @@ func TestFindByNeighbors(t *testing.T) { t.Fatal(err) } defer tx.Rollback(ctx) - b := &RoutesBackend{pool: pool} + b := &RoutesBackend{ + pool: pool, + sources: []*config.SourceConfig{ + {ID: "rs1"}, + {ID: "rs2"}, + }, + } r := &api.LookupRoute{ State: "filtered", Neighbor: &api.Neighbor{ @@ -74,6 +82,8 @@ func TestFindByNeighbors(t *testing.T) { Network: "1.2.3.0/24", }, } + b.initTable(ctx, tx, "rs1") + b.initTable(ctx, tx, "rs2") b.persist(ctx, tx, "rs1", r, now) r.Route.ID = "r4242" @@ -85,7 +95,7 @@ func TestFindByNeighbors(t *testing.T) { r.Route.ID = "r4244" r.Neighbor.ID = "n25" - b.persist(ctx, tx, "rs1", r, now) + b.persist(ctx, tx, "rs2", r, now) if err := tx.Commit(ctx); err != nil { t.Fatal(err) @@ -113,7 +123,13 @@ func TestFindByPrefix(t *testing.T) { t.Fatal(err) } defer tx.Rollback(ctx) - b := &RoutesBackend{pool: pool} + b := &RoutesBackend{ + pool: pool, + sources: []*config.SourceConfig{ + {ID: "rs1"}, + {ID: "rs2"}, + }, + } r := &api.LookupRoute{ State: "filtered", Neighbor: &api.Neighbor{ @@ -124,6 +140,9 @@ func TestFindByPrefix(t *testing.T) { Network: "1.2.3.0/24", }, } + + b.initTable(ctx, tx, "rs1") + b.initTable(ctx, tx, "rs2") b.persist(ctx, tx, "rs1", r, now) r.Route.ID = "r4242" @@ -133,7 +152,7 @@ func TestFindByPrefix(t *testing.T) { r.Route.ID = "r4243" r.Route.Network = "1.2.5.0/24" r.Neighbor.ID = "n24" - b.persist(ctx, tx, "rs1", r, now) + b.persist(ctx, tx, "rs2", r, now) r.Route.ID = "r4244" r.Route.Network = "5.5.5.0/24"