Skip to content

Commit

Permalink
Update MySQL
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCutter committed Dec 6, 2024
1 parent ca39ee8 commit fe8cbc2
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 36 deletions.
23 changes: 7 additions & 16 deletions storage/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ func (s *Storage) writeTreeState(ctx context.Context, tx *sql.Tx, size uint64, r
// Note that if a partial tile is requested, but a larger tile is available, this
// will return the largest tile available. This could be trimmed to return only the
// number of entries specifically requested if this behaviour becomes problematic.
func (s *Storage) ReadTile(ctx context.Context, level, index, minTreeSize uint64) ([]byte, error) {
func (s *Storage) ReadTile(ctx context.Context, level, index uint64, p uint8) ([]byte, error) {
row := s.db.QueryRowContext(ctx, selectSubtreeByLevelAndIndexSQL, level, index)
if err := row.Err(); err != nil {
return nil, err
Expand All @@ -257,28 +257,19 @@ func (s *Storage) ReadTile(ctx context.Context, level, index, minTreeSize uint64
return nil, fmt.Errorf("scan tile: %v", err)
}

requestedWidth := partialTileSize(level, index, minTreeSize)
numEntries := uint64(len(tile) / sha256.Size)

if requestedWidth > numEntries {
requestedEntries := uint64(p)
if requestedEntries == 0 {
requestedEntries = 256
}
if requestedEntries > numEntries {
// If the user has requested a size larger than we have, they can't have it
return nil, os.ErrNotExist
}

return tile, nil
}

// partialTileSize returns the expected number of leaves in a tile at the given location within
// a tree of the specified logSize, or 0 if the tile is expected to be fully populated.
func partialTileSize(level, index, logSize uint64) uint64 {
sizeAtLevel := logSize >> (level * 8)
fullTiles := sizeAtLevel / 256
if index < fullTiles {
return 256
}
return sizeAtLevel % 256
}

// writeTile replaces the tile nodes at the given level and index.
func (s *Storage) writeTile(ctx context.Context, tx *sql.Tx, level, index uint64, nodes []byte) error {
if _, err := tx.ExecContext(ctx, replaceSubtreeSQL, level, index, nodes); err != nil {
Expand All @@ -298,7 +289,7 @@ func (s *Storage) writeTile(ctx context.Context, tx *sql.Tx, level, index uint64
// 3. Partial tile request with full/larger partial tile output: Return trimmed partial tile with correct tile width.
// 4. Partial tile request with partial tile (same width) output: Return partial tile.
// 5. Partial tile request with smaller partial tile output: Return error.
func (s *Storage) ReadEntryBundle(ctx context.Context, index, treeSize uint64) ([]byte, error) {
func (s *Storage) ReadEntryBundle(ctx context.Context, index uint64, p uint8) ([]byte, error) {
row := s.db.QueryRowContext(ctx, selectTiledLeavesSQL, index)
if err := row.Err(); err != nil {
return nil, err
Expand Down
42 changes: 22 additions & 20 deletions storage/mysql/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,54 +189,55 @@ func TestGetTile(t *testing.T) {
}

for _, test := range []struct {
name string
level, index, treeSize uint64
wantEntries int
wantNotFound bool
name string
level, index uint64
p uint8
wantEntries int
wantNotFound bool
}{
{
name: "requested partial tile for a complete tile",
level: 0, index: 0, treeSize: 10,
level: 0, index: 0, p: 10,
wantEntries: 256,
wantNotFound: false,
},
{
name: "too small but that's ok",
level: 0, index: 1, treeSize: uint64(treeSize) - 1,
level: 0, index: 1, p: layout.PartialTileSize(0, 1, uint64(treeSize-1)),
wantEntries: 2,
wantNotFound: false,
},
{
name: "just right",
level: 0, index: 1, treeSize: uint64(treeSize),
level: 0, index: 1, p: layout.PartialTileSize(0, 1, uint64(treeSize)),
wantEntries: 2,
wantNotFound: false,
},
{
name: "too big",
level: 0, index: 1, treeSize: uint64(treeSize + 1),
level: 0, index: 1, p: layout.PartialTileSize(0, 1, uint64(treeSize+1)),
wantNotFound: true,
},
{
name: "level 1 too small",
level: 1, index: 0, treeSize: uint64(treeSize - 1),
level: 1, index: 0, p: layout.PartialTileSize(1, 0, uint64(treeSize-1)),
wantEntries: 1,
wantNotFound: false,
},
{
name: "level 1 just right",
level: 1, index: 0, treeSize: uint64(treeSize),
level: 1, index: 0, p: layout.PartialTileSize(1, 0, uint64(treeSize)),
wantEntries: 1,
wantNotFound: false,
},
{
name: "level 1 too big",
level: 1, index: 0, treeSize: 550,
level: 1, index: 0, p: layout.PartialTileSize(1, 0, 550),
wantNotFound: true,
},
} {
t.Run(test.name, func(t *testing.T) {
tile, err := s.ReadTile(ctx, test.level, test.index, test.treeSize)
tile, err := s.ReadTile(ctx, test.level, test.index, test.p)
if err != nil {
if notFound, wantNotFound := os.IsNotExist(err), test.wantNotFound; notFound != wantNotFound {
t.Errorf("wantNotFound %v but notFound %v", wantNotFound, notFound)
Expand All @@ -259,20 +260,21 @@ func TestReadMissingTile(t *testing.T) {
s := newTestMySQLStorage(t, ctx)

for _, test := range []struct {
name string
level, index, width uint64
name string
level, index uint64
p uint8
}{
{
name: "0/0/0",
level: 0, index: 0, width: 0,
level: 0, index: 0, p: 0,
},
{
name: "123/456/789",
level: 123, index: 456, width: 789,
level: 123, index: 456, p: 789 % layout.TileWidth,
},
} {
t.Run(test.name, func(t *testing.T) {
tile, err := s.ReadTile(ctx, test.level, test.index, test.width)
tile, err := s.ReadTile(ctx, test.level, test.index, test.p)
if err != nil {
if os.IsNotExist(err) {
// this is success for this test
Expand Down Expand Up @@ -305,7 +307,7 @@ func TestReadMissingEntryBundle(t *testing.T) {
},
} {
t.Run(test.name, func(t *testing.T) {
entryBundle, err := s.ReadEntryBundle(ctx, test.index, test.index)
entryBundle, err := s.ReadEntryBundle(ctx, test.index, uint8(test.index%layout.TileWidth))
if err != nil {
if os.IsNotExist(err) {
// this is success for this test
Expand Down Expand Up @@ -385,7 +387,7 @@ func TestTileRoundTrip(t *testing.T) {
}

tileLevel, tileIndex, _, nodeIndex := layout.NodeCoordsToTileAddress(0, entryIndex)
tileRaw, err := s.ReadTile(ctx, tileLevel, tileIndex, nodeIndex+1)
tileRaw, err := s.ReadTile(ctx, tileLevel, tileIndex, uint8(nodeIndex+1))
if err != nil {
t.Errorf("ReadTile got err: %v", err)
}
Expand Down Expand Up @@ -434,7 +436,7 @@ func TestEntryBundleRoundTrip(t *testing.T) {
if err != nil {
t.Errorf("Add got err: %v", err)
}
entryBundleRaw, err := s.ReadEntryBundle(ctx, entryIndex/256, entryIndex)
entryBundleRaw, err := s.ReadEntryBundle(ctx, entryIndex/256, uint8(entryIndex%layout.TileWidth))
if err != nil {
t.Errorf("ReadEntryBundle got err: %v", err)
}
Expand Down

0 comments on commit fe8cbc2

Please sign in to comment.