github.com/matrixorigin/matrixone@v1.2.0/pkg/objectio/writer_test.go (about)

     1  // Copyright 2021 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package objectio
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"math"
    21  	"os"
    22  	"path"
    23  	"path/filepath"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    28  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    29  	"github.com/matrixorigin/matrixone/pkg/container/types"
    30  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    31  	"github.com/matrixorigin/matrixone/pkg/defines"
    32  	"github.com/matrixorigin/matrixone/pkg/fileservice"
    33  	"github.com/stretchr/testify/assert"
    34  	"github.com/stretchr/testify/require"
    35  )
    36  
    37  const (
    38  	ModuleName = "ObjectIo"
    39  )
    40  
    41  func GetDefaultTestPath(module string, name string) string {
    42  	return filepath.Join("/tmp", module, name)
    43  }
    44  
    45  func MakeDefaultTestPath(module string, name string) string {
    46  	path := GetDefaultTestPath(module, name)
    47  	os.MkdirAll(path, os.FileMode(0755))
    48  	return path
    49  }
    50  
    51  func RemoveDefaultTestPath(module string, name string) {
    52  	path := GetDefaultTestPath(module, name)
    53  	os.RemoveAll(path)
    54  }
    55  
    56  func InitTestEnv(module string, name string) string {
    57  	RemoveDefaultTestPath(module, name)
    58  	return MakeDefaultTestPath(module, name)
    59  }
    60  
    61  func TestNewObjectWriter(t *testing.T) {
    62  	ctx := context.Background()
    63  
    64  	dir := InitTestEnv(ModuleName, t.Name())
    65  	dir = path.Join(dir, "/local")
    66  	id := 1
    67  	name := fmt.Sprintf("%d.blk", id)
    68  	mp := mpool.MustNewZero()
    69  	bat := newBatch(mp)
    70  	defer bat.Clean(mp)
    71  	bat2 := newBatch2(mp)
    72  	defer bat.Clean(mp)
    73  	c := fileservice.Config{
    74  		Name:    defines.LocalFileServiceName,
    75  		Backend: "DISK",
    76  		DataDir: dir,
    77  		Cache:   fileservice.DisabledCacheConfig,
    78  	}
    79  	service, err := fileservice.NewFileService(ctx, c, nil)
    80  	assert.Nil(t, err)
    81  	defer service.Close()
    82  
    83  	objectWriter, err := NewObjectWriterSpecial(WriterNormal, name, service)
    84  	assert.Nil(t, err)
    85  	objectWriter.SetAppendable()
    86  	//objectWriter.pkColIdx = 3
    87  	fd, err := objectWriter.Write(bat)
    88  	assert.Nil(t, err)
    89  	for i := range bat.Vecs {
    90  		zbuf := make([]byte, 64)
    91  		zbuf[31] = 1
    92  		zbuf[63] = 10
    93  		fd.ColumnMeta(uint16(i)).SetZoneMap(zbuf)
    94  	}
    95  	_, err = objectWriter.Write(bat)
    96  	assert.Nil(t, err)
    97  	_, err = objectWriter.WriteWithoutSeqnum(bat2)
    98  	assert.Nil(t, err)
    99  	ts := time.Now()
   100  	option := WriteOptions{
   101  		Type: WriteTS,
   102  		Val:  ts,
   103  	}
   104  	blocks, err := objectWriter.WriteEnd(context.Background(), option)
   105  	assert.Nil(t, err)
   106  	assert.Equal(t, 3, len(blocks))
   107  	assert.Nil(t, objectWriter.buffer)
   108  	require.Equal(t, objectWriter.objStats[0].Size(), blocks[0].GetExtent().End()+FooterSize)
   109  
   110  	objectReader, _ := NewObjectReaderWithStr(name, service)
   111  	extents := make([]Extent, 3)
   112  	for i, blk := range blocks {
   113  		extents[i] = NewExtent(1, blk.GetExtent().Offset(), blk.GetExtent().Length(), blk.GetExtent().OriginSize())
   114  	}
   115  	pool, err := mpool.NewMPool("objectio_test", 0, mpool.NoFixed)
   116  	assert.NoError(t, err)
   117  	nb0 := pool.CurrNB()
   118  	objectReader.CacheMetaExtent(&extents[0])
   119  	metaHeader, err := objectReader.ReadMeta(context.Background(), pool)
   120  	assert.Nil(t, err)
   121  	meta, _ := metaHeader.DataMeta()
   122  	oSize := uint32(0)
   123  	for i := uint32(0); i < 3; i++ {
   124  		blockMeta := meta.GetBlockMeta(i)
   125  		for y := uint16(0); y < blockMeta.GetColumnCount(); y++ {
   126  			oSize += blockMeta.MustGetColumn(y).Location().OriginSize()
   127  		}
   128  	}
   129  	oSize += meta.BlockHeader().BFExtent().OriginSize()
   130  	oSize += meta.BlockHeader().ZoneMapArea().OriginSize()
   131  	// 24 is the size of empty bf and zm
   132  	oSize += HeaderSize + FooterSize + 24 + extents[0].OriginSize()
   133  	require.Equal(t, objectWriter.objStats[0].OriginSize(), oSize)
   134  	assert.Equal(t, uint32(3), meta.BlockCount())
   135  	assert.True(t, meta.BlockHeader().Appendable())
   136  	assert.Equal(t, uint16(math.MaxUint16), meta.BlockHeader().SortKey())
   137  	idxs := make([]uint16, 3)
   138  	idxs[0] = 0
   139  	idxs[1] = 2
   140  	idxs[2] = 3
   141  	typs := []types.Type{types.T_int8.ToType(), types.T_int32.ToType(), types.T_int64.ToType()}
   142  	vec, err := objectReader.ReadOneBlock(context.Background(), idxs, typs, 0, pool)
   143  	assert.Nil(t, err)
   144  	defer vec.Release()
   145  
   146  	obj, err := Decode(vec.Entries[0].CachedData.Bytes())
   147  	assert.Nil(t, err)
   148  	vector1 := obj.(*vector.Vector)
   149  	assert.Equal(t, int8(3), vector.MustFixedCol[int8](vector1)[3])
   150  
   151  	obj, err = Decode(vec.Entries[1].CachedData.Bytes())
   152  	assert.Nil(t, err)
   153  	vector2 := obj.(*vector.Vector)
   154  	assert.Equal(t, int32(3), vector.MustFixedCol[int32](vector2)[3])
   155  
   156  	obj, err = Decode(vec.Entries[2].CachedData.Bytes())
   157  	assert.Nil(t, err)
   158  	vector3 := obj.(*vector.Vector)
   159  	assert.Equal(t, int64(3), vector.GetFixedAt[int64](vector3, 3))
   160  
   161  	blk := blocks[0].MustGetColumn(idxs[0])
   162  	buf := blk.ZoneMap()
   163  	assert.Equal(t, uint8(0x1), buf[31])
   164  	assert.Equal(t, uint8(0xa), buf[63])
   165  	assert.True(t, nb0 == pool.CurrNB())
   166  
   167  	fs := NewObjectFS(service, dir)
   168  	dirs, err := fs.ListDir("")
   169  	assert.Nil(t, err)
   170  	assert.Equal(t, 1, len(dirs))
   171  	objectReader, err = NewObjectReaderWithStr(name, service)
   172  	assert.Nil(t, err)
   173  	metaHeader, err = objectReader.ReadAllMeta(context.Background(), pool)
   174  	assert.Nil(t, err)
   175  	meta, _ = metaHeader.DataMeta()
   176  	assert.Equal(t, uint32(3), meta.BlockCount())
   177  	assert.Nil(t, err)
   178  	assert.Equal(t, uint32(3), meta.BlockCount())
   179  	idxs = make([]uint16, 3)
   180  	idxs[0] = 0
   181  	idxs[1] = 2
   182  	idxs[2] = 3
   183  	vec, err = objectReader.ReadOneBlock(context.Background(), idxs, typs, 0, pool)
   184  	assert.Nil(t, err)
   185  	defer vec.Release()
   186  
   187  	obj, err = Decode(vec.Entries[0].CachedData.Bytes())
   188  	assert.Nil(t, err)
   189  	vector1 = obj.(*vector.Vector)
   190  	assert.Equal(t, int8(3), vector.MustFixedCol[int8](vector1)[3])
   191  
   192  	obj, err = Decode(vec.Entries[1].CachedData.Bytes())
   193  	assert.Nil(t, err)
   194  	vector2 = obj.(*vector.Vector)
   195  	assert.Equal(t, int32(3), vector.MustFixedCol[int32](vector2)[3])
   196  
   197  	obj, err = Decode(vec.Entries[2].CachedData.Bytes())
   198  	assert.Nil(t, err)
   199  	vector3 = obj.(*vector.Vector)
   200  	assert.Equal(t, int64(3), vector.GetFixedAt[int64](vector3, 3))
   201  	blk = blocks[0].MustGetColumn(idxs[0])
   202  	buf = blk.ZoneMap()
   203  	assert.Equal(t, uint8(0x1), buf[31])
   204  	assert.Equal(t, uint8(0xa), buf[63])
   205  	assert.True(t, nb0 == pool.CurrNB())
   206  	buf1, err := objectReader.ReadExtent(context.Background(), meta.BlockHeader().ZoneMapArea())
   207  	assert.Nil(t, err)
   208  	zma := ZoneMapArea(buf1)
   209  	buf = zma.GetZoneMap(0, 0)
   210  	assert.Equal(t, uint8(0x1), buf[31])
   211  	assert.Equal(t, uint8(0xa), buf[63])
   212  }
   213  
   214  func getObjectMeta(ctx context.Context, t *testing.B) ObjectDataMeta {
   215  	dir := InitTestEnv(ModuleName, t.Name())
   216  	dir = path.Join(dir, "/local")
   217  	id := 1
   218  	name := fmt.Sprintf("%d.blk", id)
   219  	mp := mpool.MustNewZero()
   220  	bat := newBatch(mp)
   221  	defer bat.Clean(mp)
   222  	c := fileservice.Config{
   223  		Name:    defines.LocalFileServiceName,
   224  		Backend: "DISK",
   225  		DataDir: dir,
   226  	}
   227  	service, err := fileservice.NewFileService(ctx, c, nil)
   228  	assert.Nil(t, err)
   229  
   230  	objectWriter, err := NewObjectWriterSpecial(WriterNormal, name, service)
   231  	assert.Nil(t, err)
   232  	for y := 0; y < 1; y++ {
   233  		fd, err := objectWriter.Write(bat)
   234  		assert.Nil(t, err)
   235  		for i := range bat.Vecs {
   236  			zbuf := make([]byte, 64)
   237  			zbuf[31] = 1
   238  			zbuf[63] = 10
   239  			fd.ColumnMeta(uint16(i)).SetZoneMap(zbuf)
   240  		}
   241  	}
   242  	ts := time.Now()
   243  	option := WriteOptions{
   244  		Type: WriteTS,
   245  		Val:  ts,
   246  	}
   247  	blocks, err := objectWriter.WriteEnd(context.Background(), option)
   248  	assert.Nil(t, err)
   249  	assert.Equal(t, 1, len(blocks))
   250  	assert.Nil(t, objectWriter.buffer)
   251  	objectReader, _ := NewObjectReaderWithStr(name, service)
   252  	ext := blocks[0].BlockHeader().MetaLocation()
   253  	objectReader.CacheMetaExtent(&ext)
   254  	metaHeader, err := objectReader.ReadMeta(context.Background(), nil)
   255  	assert.Nil(t, err)
   256  	meta, _ := metaHeader.DataMeta()
   257  	return meta
   258  }
   259  
   260  func BenchmarkMetadata(b *testing.B) {
   261  	ctx := context.Background()
   262  	meta := getObjectMeta(ctx, b)
   263  	b.Run("GetBlockMeta", func(b *testing.B) {
   264  		b.ResetTimer()
   265  		for i := 0; i < b.N; i++ {
   266  			meta.GetBlockMeta(0)
   267  		}
   268  	})
   269  	b.Log(meta.GetBlockMeta(0).GetID())
   270  	b.Run("GetColumnMeta", func(b *testing.B) {
   271  		b.ResetTimer()
   272  		for i := 0; i < b.N; i++ {
   273  			meta.Length()
   274  		}
   275  	})
   276  	b.Run("BlockCount", func(b *testing.B) {
   277  		b.ResetTimer()
   278  		for i := 0; i < b.N; i++ {
   279  			meta.BlockCount()
   280  		}
   281  	})
   282  	b.Log(meta.BlockCount())
   283  }
   284  
   285  func TestNewObjectReader(t *testing.T) {
   286  	ctx := context.Background()
   287  
   288  	dir := InitTestEnv(ModuleName, t.Name())
   289  	dir = path.Join(dir, "/local")
   290  	id := 1
   291  	name := fmt.Sprintf("%d.blk", id)
   292  	mp := mpool.MustNewZero()
   293  	bat := newBatch(mp)
   294  	defer bat.Clean(mp)
   295  	c := fileservice.Config{
   296  		Name:    defines.LocalFileServiceName,
   297  		Backend: "DISK",
   298  		DataDir: dir,
   299  	}
   300  	service, err := fileservice.NewFileService(ctx, c, nil)
   301  	assert.Nil(t, err)
   302  	defer service.Close()
   303  
   304  	objectWriter, err := NewObjectWriterSpecial(WriterNormal, name, service)
   305  	assert.Nil(t, err)
   306  	fd, err := objectWriter.Write(bat)
   307  	assert.Nil(t, err)
   308  	for i := range bat.Vecs {
   309  		zbuf := make([]byte, 64)
   310  		zbuf[31] = 1
   311  		zbuf[63] = 10
   312  		fd.ColumnMeta(uint16(i)).SetZoneMap(zbuf)
   313  	}
   314  	_, err = objectWriter.Write(bat)
   315  	assert.Nil(t, err)
   316  	_, err = objectWriter.WriteTombstone(bat)
   317  	assert.Nil(t, err)
   318  	_, _, err = objectWriter.WriteSubBlock(bat, 2)
   319  	assert.Nil(t, err)
   320  	_, _, err = objectWriter.WriteSubBlock(bat, 26)
   321  	assert.Nil(t, err)
   322  	ts := time.Now()
   323  	option := WriteOptions{
   324  		Type: WriteTS,
   325  		Val:  ts,
   326  	}
   327  	blocks, err := objectWriter.WriteEnd(context.Background(), option)
   328  	assert.Nil(t, err)
   329  	assert.Equal(t, 5, len(blocks))
   330  	assert.Nil(t, objectWriter.buffer)
   331  	objectReader, _ := NewObjectReaderWithStr(name, service)
   332  	ext := blocks[0].BlockHeader().MetaLocation()
   333  	objectReader.CacheMetaExtent(&ext)
   334  	metaHeader, err := objectReader.ReadMeta(context.Background(), nil)
   335  	assert.Nil(t, err)
   336  	meta, _ := metaHeader.DataMeta()
   337  	assert.Equal(t, uint32(2), meta.BlockCount())
   338  	meta, _ = metaHeader.TombstoneMeta()
   339  	assert.Equal(t, uint32(1), meta.BlockCount())
   340  	meta, _ = metaHeader.SubMeta(0)
   341  	assert.Equal(t, uint32(1), meta.BlockCount())
   342  	meta, _ = metaHeader.SubMeta(24)
   343  	assert.Equal(t, uint32(1), meta.BlockCount())
   344  }
   345  
   346  func newBatch(mp *mpool.MPool) *batch.Batch {
   347  	types := []types.Type{
   348  		types.T_int8.ToType(),
   349  		types.T_int16.ToType(),
   350  		types.T_int32.ToType(),
   351  		types.T_int64.ToType(),
   352  		types.T_uint16.ToType(),
   353  		types.T_uint32.ToType(),
   354  		types.T_uint8.ToType(),
   355  		types.T_uint64.ToType(),
   356  	}
   357  	return NewBatch(types, false, int(40000*2), mp)
   358  }
   359  
   360  func newBatch2(mp *mpool.MPool) *batch.Batch {
   361  	types := []types.Type{
   362  		types.T_int8.ToType(),
   363  		types.T_int16.ToType(),
   364  		types.T_int32.ToType(),
   365  		types.T_int64.ToType(),
   366  		types.T_uint16.ToType(),
   367  		types.T_uint32.ToType(),
   368  	}
   369  	return NewBatch(types, false, int(40000*2), mp)
   370  }