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 }