Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
2ec69545
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2ec69545
编写于
9月 25, 2017
作者:
A
Ashwin Agrawal
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
pgindent appendonly directory.
上级
4832071b
变更
12
展开全部
显示空白变更内容
内联
并排
Showing
12 changed file
with
2211 addition
and
2151 deletion
+2211
-2151
src/backend/access/appendonly/aosegfiles.c
src/backend/access/appendonly/aosegfiles.c
+494
-491
src/backend/access/appendonly/appendonly_compaction.c
src/backend/access/appendonly/appendonly_compaction.c
+233
-222
src/backend/access/appendonly/appendonly_visimap.c
src/backend/access/appendonly/appendonly_visimap.c
+209
-202
src/backend/access/appendonly/appendonly_visimap_entry.c
src/backend/access/appendonly/appendonly_visimap_entry.c
+159
-151
src/backend/access/appendonly/appendonly_visimap_store.c
src/backend/access/appendonly/appendonly_visimap_store.c
+143
-144
src/backend/access/appendonly/appendonly_visimap_udf.c
src/backend/access/appendonly/appendonly_visimap_udf.c
+88
-92
src/backend/access/appendonly/appendonlyam.c
src/backend/access/appendonly/appendonlyam.c
+3
-3
src/backend/access/appendonly/appendonlyblockdirectory.c
src/backend/access/appendonly/appendonlyblockdirectory.c
+363
-354
src/backend/access/appendonly/appendonlytid.c
src/backend/access/appendonly/appendonlytid.c
+25
-24
src/backend/access/appendonly/appendonlywriter.c
src/backend/access/appendonly/appendonlywriter.c
+456
-431
src/backend/access/appendonly/test/aomd_test.c
src/backend/access/appendonly/test/aomd_test.c
+30
-30
src/backend/access/appendonly/test/appendonly_visimap_test.c
src/backend/access/appendonly/test/appendonly_visimap_test.c
+8
-7
未找到文件。
src/backend/access/appendonly/aosegfiles.c
浏览文件 @
2ec69545
此差异已折叠。
点击以展开。
src/backend/access/appendonly/appendonly_compaction.c
浏览文件 @
2ec69545
...
...
@@ -140,7 +140,8 @@ AppendOnlyCompaction_ShouldCompact(
if
(
isFull
&&
hiddenTupcount
>
0
)
{
/*
* if it is a full vacuum and there is any obsolete data, do a compaction
* if it is a full vacuum and there is any obsolete data, do a
* compaction
*/
result
=
true
;
}
...
...
@@ -203,7 +204,7 @@ static void
AppendOnlySegmentFileTruncateToEOF
(
Relation
aorel
,
FileSegInfo
*
fsinfo
)
{
const
char
*
relname
=
RelationGetRelationName
(
aorel
);
const
char
*
relname
=
RelationGetRelationName
(
aorel
);
MirroredAppendOnlyOpen
mirroredOpened
;
int32
fileSegNo
;
char
filenamepath
[
MAXPGPATH
];
...
...
@@ -215,7 +216,7 @@ AppendOnlySegmentFileTruncateToEOF(Relation aorel,
segno
=
fsinfo
->
segno
;
relname
=
RelationGetRelationName
(
aorel
);
segeof
=
(
int64
)
fsinfo
->
eof
;
segeof
=
(
int64
)
fsinfo
->
eof
;
/* Open and truncate the relation segfile beyond its eof */
MakeAOSegmentFileName
(
aorel
,
segno
,
-
1
,
&
fileSegNo
,
filenamepath
);
...
...
@@ -273,7 +274,7 @@ AppendOnlyMoveTuple(MemTuple tuple,
Assert
(
mt_bind
);
Assert
(
estate
);
oldAoTupleId
=
(
AOTupleId
*
)
slot_get_ctid
(
slot
);
oldAoTupleId
=
(
AOTupleId
*
)
slot_get_ctid
(
slot
);
/* Extract all the values of the tuple */
slot_getallattrs
(
slot
);
...
...
@@ -286,7 +287,7 @@ AppendOnlyMoveTuple(MemTuple tuple,
/* insert index' tuples if needed */
if
(
resultRelInfo
->
ri_NumIndices
>
0
)
{
ExecInsertIndexTuples
(
slot
,
(
ItemPointer
)
&
newAoTupleId
,
estate
,
true
);
ExecInsertIndexTuples
(
slot
,
(
ItemPointer
)
&
newAoTupleId
,
estate
,
true
);
ResetPerTupleExprContext
(
estate
);
}
...
...
@@ -308,7 +309,7 @@ AppendOnlyThrowAwayTuple(
Assert
(
slot
);
Assert
(
mt_bind
);
oldAoTupleId
=
(
AOTupleId
*
)
slot_get_ctid
(
slot
);
oldAoTupleId
=
(
AOTupleId
*
)
slot_get_ctid
(
slot
);
/* Extract all the values of the tuple */
slot_getallattrs
(
slot
);
...
...
@@ -330,9 +331,9 @@ AppendOnlyThrowAwayTuple(
static
void
AppendOnlySegmentFileFullCompaction
(
Relation
aorel
,
AppendOnlyInsertDesc
insertDesc
,
FileSegInfo
*
fsinfo
)
FileSegInfo
*
fsinfo
)
{
const
char
*
relname
;
const
char
*
relname
;
AppendOnlyVisimap
visiMap
;
AppendOnlyScanDesc
scanDesc
;
TupleDesc
tupDesc
;
...
...
@@ -404,7 +405,7 @@ AppendOnlySegmentFileFullCompaction(Relation aorel,
/* Check interrupts as this may take time. */
CHECK_FOR_INTERRUPTS
();
aoTupleId
=
(
AOTupleId
*
)
slot_get_ctid
(
slot
);
aoTupleId
=
(
AOTupleId
*
)
slot_get_ctid
(
slot
);
if
(
AppendOnlyVisimap_IsVisible
(
&
scanDesc
->
visibilityMap
,
aoTupleId
))
{
AppendOnlyMoveTuple
(
tuple
,
...
...
@@ -472,6 +473,7 @@ bool
HasLockForSegmentFileDrop
(
Relation
aorel
)
{
LockAcquireResult
acquireResult
=
LockRelationNoWait
(
aorel
,
AccessExclusiveLock
);
switch
(
acquireResult
)
{
case
LOCKACQUIRE_ALREADY_HELD
:
...
...
@@ -505,24 +507,25 @@ HasLockForSegmentFileDrop(Relation aorel)
void
AppendOnlyDrop
(
Relation
aorel
,
List
*
compaction_segno
)
{
const
char
*
relname
;
const
char
*
relname
;
int
total_segfiles
;
FileSegInfo
**
segfile_array
;
int
i
,
segno
;
FileSegInfo
*
fsinfo
;
FileSegInfo
**
segfile_array
;
int
i
,
segno
;
FileSegInfo
*
fsinfo
;
Assert
(
Gp_role
==
GP_ROLE_EXECUTE
||
Gp_role
==
GP_ROLE_UTILITY
);
Assert
(
RelationIsAoRows
(
aorel
));
Assert
(
Gp_role
==
GP_ROLE_EXECUTE
||
Gp_role
==
GP_ROLE_UTILITY
);
Assert
(
RelationIsAoRows
(
aorel
));
relname
=
RelationGetRelationName
(
aorel
);
elogif
(
Debug_appendonly_print_compaction
,
LOG
,
elogif
(
Debug_appendonly_print_compaction
,
LOG
,
"Drop AO relation %s"
,
relname
);
/* Get information about all the file segments we need to scan */
segfile_array
=
GetAllFileSegInfo
(
aorel
,
SnapshotNow
,
&
total_segfiles
);
for
(
i
=
0
;
i
<
total_segfiles
;
i
++
)
for
(
i
=
0
;
i
<
total_segfiles
;
i
++
)
{
segno
=
segfile_array
[
i
]
->
segno
;
if
(
!
list_member_int
(
compaction_segno
,
segno
))
...
...
@@ -531,9 +534,11 @@ AppendOnlyDrop(Relation aorel, List *compaction_segno)
}
/*
* Try to get the transaction write-lock for the Append-Only segment file.
* Try to get the transaction write-lock for the Append-Only segment
* file.
*
* NOTE: This is a transaction scope lock that must be held until commit / abort.
* NOTE: This is a transaction scope lock that must be held until
* commit / abort.
*/
LockRelationAppendOnlySegmentFile
(
&
aorel
->
rd_node
,
...
...
@@ -570,31 +575,34 @@ AppendOnlyDrop(Relation aorel, List *compaction_segno)
void
AppendOnlyTruncateToEOF
(
Relation
aorel
)
{
const
char
*
relname
;
const
char
*
relname
;
int
total_segfiles
;
FileSegInfo
**
segfile_array
;
int
i
,
segno
;
FileSegInfo
**
segfile_array
;
int
i
,
segno
;
LockAcquireResult
acquireResult
;
FileSegInfo
*
fsinfo
;
FileSegInfo
*
fsinfo
;
Assert
(
RelationIsAoRows
(
aorel
));
Assert
(
RelationIsAoRows
(
aorel
));
relname
=
RelationGetRelationName
(
aorel
);
elogif
(
Debug_appendonly_print_compaction
,
LOG
,
elogif
(
Debug_appendonly_print_compaction
,
LOG
,
"Compact AO relation %s"
,
relname
);
/* Get information about all the file segments we need to scan */
segfile_array
=
GetAllFileSegInfo
(
aorel
,
SnapshotNow
,
&
total_segfiles
);
for
(
i
=
0
;
i
<
total_segfiles
;
i
++
)
for
(
i
=
0
;
i
<
total_segfiles
;
i
++
)
{
segno
=
segfile_array
[
i
]
->
segno
;
/*
* Try to get the transaction write-lock for the Append-Only segment file.
* Try to get the transaction write-lock for the Append-Only segment
* file.
*
* NOTE: This is a transaction scope lock that must be held until commit / abort.
* NOTE: This is a transaction scope lock that must be held until
* commit / abort.
*/
acquireResult
=
LockRelationAppendOnlySegmentFile
(
&
aorel
->
rd_node
,
...
...
@@ -613,8 +621,8 @@ AppendOnlyTruncateToEOF(Relation aorel)
/*
* This should not occur since this segfile info was found by the
* "all" method, but better to catch for trouble shooting
*
(possibly
index corruption?)
* "all" method, but better to catch for trouble shooting
(possibly
* index corruption?)
*/
if
(
fsinfo
==
NULL
)
elog
(
ERROR
,
"file seginfo for AO relation %s %u/%u/%u (segno=%u) is missing"
,
...
...
@@ -649,23 +657,24 @@ AppendOnlyTruncateToEOF(Relation aorel)
*/
void
AppendOnlyCompact
(
Relation
aorel
,
List
*
compaction_segno
,
List
*
compaction_segno
,
int
insert_segno
,
bool
isFull
)
{
const
char
*
relname
;
const
char
*
relname
;
int
total_segfiles
;
FileSegInfo
**
segfile_array
;
FileSegInfo
**
segfile_array
;
AppendOnlyInsertDesc
insertDesc
=
NULL
;
int
i
,
segno
;
FileSegInfo
*
fsinfo
;
int
i
,
segno
;
FileSegInfo
*
fsinfo
;
Assert
(
Gp_role
==
GP_ROLE_EXECUTE
||
Gp_role
==
GP_ROLE_UTILITY
);
Assert
(
Gp_role
==
GP_ROLE_EXECUTE
||
Gp_role
==
GP_ROLE_UTILITY
);
Assert
(
insert_segno
>=
0
);
relname
=
RelationGetRelationName
(
aorel
);
elogif
(
Debug_appendonly_print_compaction
,
LOG
,
elogif
(
Debug_appendonly_print_compaction
,
LOG
,
"Compact AO relation %s"
,
relname
);
/* Get information about all the file segments we need to scan */
...
...
@@ -673,7 +682,7 @@ AppendOnlyCompact(Relation aorel,
insertDesc
=
appendonly_insert_init
(
aorel
,
insert_segno
,
false
);
for
(
i
=
0
;
i
<
total_segfiles
;
i
++
)
for
(
i
=
0
;
i
<
total_segfiles
;
i
++
)
{
segno
=
segfile_array
[
i
]
->
segno
;
if
(
!
list_member_int
(
compaction_segno
,
segno
))
...
...
@@ -687,9 +696,11 @@ AppendOnlyCompact(Relation aorel,
}
/*
* Try to get the transaction write-lock for the Append-Only segment file.
* Try to get the transaction write-lock for the Append-Only segment
* file.
*
* NOTE: This is a transaction scope lock that must be held until commit / abort.
* NOTE: This is a transaction scope lock that must be held until
* commit / abort.
*/
LockRelationAppendOnlySegmentFile
(
&
aorel
->
rd_node
,
...
...
@@ -702,8 +713,8 @@ AppendOnlyCompact(Relation aorel,
/*
* This should not occur since this segfile info was found by the
* "all" method, but better to catch for trouble shooting
*
(possibly
index corruption?)
* "all" method, but better to catch for trouble shooting
(possibly
* index corruption?)
*/
if
(
fsinfo
==
NULL
)
elog
(
ERROR
,
"file seginfo for AO relation %s %u/%u/%u (segno=%u) is missing"
,
...
...
@@ -758,7 +769,7 @@ AppendOnlyCompaction_IsRelationEmpty(Relation aorel)
pg_aoseg_rel
=
heap_open
(
aorel
->
rd_appendonly
->
segrelid
,
AccessShareLock
);
pg_aoseg_dsc
=
RelationGetDescr
(
pg_aoseg_rel
);
aoscan
=
heap_beginscan
(
pg_aoseg_rel
,
SnapshotNow
,
0
,
NULL
);
Anum_tupcount
=
RelationIsAoRows
(
aorel
)
?
Anum_pg_aoseg_tupcount
:
Anum_pg_aocs_tupcount
;
Anum_tupcount
=
RelationIsAoRows
(
aorel
)
?
Anum_pg_aoseg_tupcount
:
Anum_pg_aocs_tupcount
;
while
((
tuple
=
heap_getnext
(
aoscan
,
ForwardScanDirection
))
!=
NULL
&&
empty
)
{
...
...
src/backend/access/appendonly/appendonly_visimap.c
浏览文件 @
2ec69545
...
...
@@ -29,12 +29,12 @@ typedef struct AppendOnlyVisiMapDeleteKey
/*
* Segno of the dirty visimap entry.
*
* MPP-23546: Changed the type of segno from int to uint64. With
*
uint (4-bytes), additional 4-bytes were being used for padding.
*
The padding bits may differ for two keys causing two otherwis
e
*
equal objects to be treated as unequal by hash functions.
*
Keeping type to uint64 does not change the value of
*
sizeof(AppendOnlyVisiMapDeleteKey) but eliminates
padding.
* MPP-23546: Changed the type of segno from int to uint64. With
uint
*
(4-bytes), additional 4-bytes were being used for padding. The padding
*
bits may differ for two keys causing two otherwise equal objects to b
e
*
treated as unequal by hash functions. Keeping type to uint64 does not
*
change the value of sizeof(AppendOnlyVisiMapDeleteKey) but eliminates
* padding.
*/
uint64
segno
;
...
...
@@ -55,8 +55,8 @@ typedef struct AppendOnlyVisiMapDeleteData
AppendOnlyVisiMapDeleteKey
key
;
/*
* Offset of the latest dirty version of the visimap bitmap in
*
the spill
file.
* Offset of the latest dirty version of the visimap bitmap in
the spill
* file.
*/
uint64
workFileOffset
;
...
...
@@ -158,7 +158,7 @@ AppendOnlyVisimap_Find(
Assert
(
visiMap
);
Assert
(
aoTupleId
);
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map: Find entry for "
"(tupleId) = %s"
,
AOTupleIdToString
(
aoTupleId
));
...
...
@@ -190,7 +190,7 @@ AppendOnlyVisimap_IsVisible(
{
Assert
(
visiMap
);
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map: Visibility check: "
"(tupleId) = %s"
,
AOTupleIdToString
(
aoTupleId
));
...
...
@@ -281,7 +281,7 @@ AppendOnlyVisimap_GetSegmentFileHiddenTupleCount(
*/
void
AppendOnlyVisimapScan_Init
(
AppendOnlyVisimapScan
*
visiMapScan
,
AppendOnlyVisimapScan
*
visiMapScan
,
Oid
visimapRelid
,
Oid
visimapIdxid
,
LOCKMODE
lockmode
,
...
...
@@ -319,7 +319,7 @@ AppendOnlyVisimapScan_GetNextInvisible(
Assert
(
tupleId
);
Assert
(
!
visiMapScan
->
isFinished
);
found
=
false
;
found
=
false
;
while
(
!
found
&&
!
visiMapScan
->
isFinished
)
{
if
(
!
AppendOnlyVisimapEntry_IsValid
(
...
...
@@ -332,7 +332,7 @@ AppendOnlyVisimapScan_GetNextInvisible(
&
visiMapScan
->
visimap
.
visimapEntry
,
NULL
))
{
visiMapScan
->
isFinished
=
true
;
visiMapScan
->
isFinished
=
true
;
return
false
;
}
AOTupleIdInit_Init
(
tupleId
);
...
...
@@ -343,8 +343,7 @@ AppendOnlyVisimapScan_GetNextInvisible(
tupleId
))
{
/*
* no more invisible tuples in this visimap entry.
* Try next one
* no more invisible tuples in this visimap entry. Try next one
*/
AppendOnlyVisimapEntry_Reset
(
&
visiMapScan
->
visimap
.
visimapEntry
);
}
...
...
@@ -396,6 +395,7 @@ hash_compare_keys(const void *key1, const void *key2, Size keysize)
Assert
(
keysize
==
sizeof
(
AppendOnlyVisiMapDeleteKey
));
AppendOnlyVisiMapDeleteKey
*
k1
=
(
AppendOnlyVisiMapDeleteKey
*
)
key1
;
AppendOnlyVisiMapDeleteKey
*
k2
=
(
AppendOnlyVisiMapDeleteKey
*
)
key2
;
if
((
k1
->
segno
==
k2
->
segno
)
&&
(
k1
->
firstRowNum
==
k2
->
firstRowNum
))
{
return
0
;
...
...
@@ -451,7 +451,7 @@ AppendOnlyVisimapDelete_RebuildEntry(AppendOnlyVisimapEntry *visimapEntry, int s
MemoryContext
oldContext
;
size_t
dataSize
;
visimapEntry
->
segmentFileNum
=
segno
;
visimapEntry
->
segmentFileNum
=
segno
;
visimapEntry
->
firstRowNum
=
firstRowNum
;
dataSize
=
VARSIZE
(
visimapEntry
->
data
)
-
...
...
@@ -462,8 +462,8 @@ AppendOnlyVisimapDelete_RebuildEntry(AppendOnlyVisimapEntry *visimapEntry, int s
MemoryContextSwitchTo
(
oldContext
);
/*
* We only stash away a visimap entry when it is dirty. Thus, we mark
*
the
visimap entry again as dirty during unstash
* We only stash away a visimap entry when it is dirty. Thus, we mark
the
* visimap entry again as dirty during unstash
*/
visimapEntry
->
dirty
=
true
;
memcpy
(
&
visimapEntry
->
tupleTid
,
tid
,
sizeof
(
ItemPointerData
));
...
...
@@ -477,14 +477,15 @@ AppendOnlyVisimapDelete_Unstash(
AppendOnlyVisimapDelete
*
visiMapDelete
,
int
segno
,
int64
firstRowNum
,
AppendOnlyVisiMapDeleteData
*
deleteData
)
{
AppendOnlyVisimap
*
visiMap
;
uint64
len
,
dataLen
;
uint64
len
,
dataLen
;
AppendOnlyVisiMapDeleteKey
key
;
Assert
(
visiMapDelete
);
visiMap
=
visiMapDelete
->
visiMap
;
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map delete: Unstash dirty visimap entry %d/"
INT64_FORMAT
", offset "
INT64_FORMAT
,
segno
,
firstRowNum
,
deleteData
->
workFileOffset
);
...
...
@@ -515,7 +516,7 @@ AppendOnlyVisimapDelete_Unstash(
/* Now read the remaining part of the entry */
len
=
ExecWorkFile_Read
(
visiMapDelete
->
workfile
,
((
char
*
)
visiMap
->
visimapEntry
.
data
)
+
4
,
dataLen
-
4
);
((
char
*
)
visiMap
->
visimapEntry
.
data
)
+
4
,
dataLen
-
4
);
if
(
len
!=
dataLen
-
4
)
{
elog
(
ERROR
,
"Failed to read visimap delete spill data: %d/"
INT64_FORMAT
...
...
@@ -561,11 +562,12 @@ AppendOnlyVisimapDelete_Find(
key
.
segno
=
AOTupleIdGet_segmentFileNum
(
aoTupleId
);
key
.
firstRowNum
=
firstRowNum
;
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map delete: Search dirty visimap entry "
INT64_FORMAT
"/"
INT64_FORMAT
,
key
.
segno
,
key
.
firstRowNum
);
bool
found
=
false
;
r
=
hash_search
(
visiMapDelete
->
dirtyEntryCache
,
&
key
,
HASH_FIND
,
&
found
);
...
...
@@ -573,7 +575,7 @@ AppendOnlyVisimapDelete_Find(
{
Assert
(
r
);
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map delete: Found dirty visimap entry "
INT64_FORMAT
"/"
INT64_FORMAT
,
r
->
key
.
segno
,
r
->
key
.
firstRowNum
);
...
...
@@ -636,7 +638,7 @@ AppendOnlyVisimapDelete_Stash(
offset
=
ExecWorkFile_GetSize
(
visiMapDelete
->
workfile
);
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map delete: Stash dirty visimap entry %d/"
INT64_FORMAT
,
visiMap
->
visimapEntry
.
segmentFileNum
,
visiMap
->
visimapEntry
.
firstRowNum
);
...
...
@@ -691,7 +693,7 @@ AppendOnlyVisimapDelete_Hide(
Assert
(
visiMapDelete
);
Assert
(
aoTupleId
);
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map delete: Hide tuple "
"(tupleId) = %s"
,
AOTupleIdToString
(
aoTupleId
));
...
...
@@ -718,7 +720,9 @@ static void
AppendOnlyVisimapDelete_WriteBackStashedEntries
(
AppendOnlyVisimapDelete
*
visiMapDelete
)
{
AppendOnlyVisiMapDeleteData
*
deleteData
;
int64
len
,
dataLen
,
currentOffset
=
0
;
int64
len
,
dataLen
,
currentOffset
=
0
;
AppendOnlyVisimap
*
visiMap
;
bool
found
;
AppendOnlyVisiMapDeleteKey
key
;
...
...
@@ -757,14 +761,16 @@ AppendOnlyVisimapDelete_WriteBackStashedEntries(AppendOnlyVisimapDelete *visiMap
/* Now read the remaining part of the entry */
len
=
ExecWorkFile_Read
(
visiMapDelete
->
workfile
,
((
char
*
)
visiMap
->
visimapEntry
.
data
)
+
4
,
dataLen
-
4
);
((
char
*
)
visiMap
->
visimapEntry
.
data
)
+
4
,
dataLen
-
4
);
if
(
len
!=
(
dataLen
-
4
))
{
elog
(
ERROR
,
"Failed to read visimap delete spill data"
);
}
/* Now we search the hash entry and check if we here have the most recent
* version of the visimap entry */
/*
* Now we search the hash entry and check if we here have the most
* recent version of the visimap entry
*/
found
=
false
;
deleteData
=
hash_search
(
visiMapDelete
->
dirtyEntryCache
,
&
key
,
HASH_FIND
,
&
found
);
...
...
@@ -786,8 +792,10 @@ AppendOnlyVisimapDelete_WriteBackStashedEntries(AppendOnlyVisimapDelete *visiMap
}
else
{
/* Until this point on the data field of the visimap entry has valid
* information. After this the visimap entry is fully rebuild.
/*
* Until this point on the data field of the visimap entry has
* valid information. After this the visimap entry is fully
* rebuild.
*/
AppendOnlyVisimapDelete_RebuildEntry
(
&
visiMap
->
visimapEntry
,
deleteData
->
key
.
segno
,
...
...
@@ -826,16 +834,15 @@ AppendOnlyVisimapDelete_Finish(
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Write-back all dirty visimap entries"
);
/*
* Write back the current change because it is be definition the
* newest.
* Write back the current change because it is be definition the newest.
*/
if
(
AppendOnlyVisimapEntry_HasChanged
(
&
visiMap
->
visimapEntry
))
{
AppendOnlyVisimap_Store
(
visiMapDelete
->
visiMap
);
/*
* Make the hash map entry invalid so that we do not overwrite the
entry
* later
* Make the hash map entry invalid so that we do not overwrite the
*
entry
later
*/
key
.
segno
=
visiMap
->
visimapEntry
.
segmentFileNum
;
key
.
firstRowNum
=
visiMap
->
visimapEntry
.
firstRowNum
;
...
...
src/backend/access/appendonly/appendonly_visimap_entry.c
浏览文件 @
2ec69545
...
...
@@ -93,7 +93,7 @@ AppendOnlyVisimapEntry_Reset(
*/
void
AppendOnlyVisimapEntry_New
(
AppendOnlyVisimapEntry
*
visiMapEntry
,
AppendOnlyVisimapEntry
*
visiMapEntry
,
AOTupleId
*
tupleId
)
{
Assert
(
visiMapEntry
);
...
...
@@ -140,6 +140,7 @@ AppendOnlyVisiMapEnty_ReadData(
Assert
(
CurrentMemoryContext
==
visiMapEntry
->
memoryContext
);
BitmapDecompressState
decompressState
;
BitmapDecompress_Init
(
&
decompressState
,
visiMapEntry
->
data
->
data
,
dataSize
);
...
...
@@ -207,7 +208,7 @@ AppendOnlyVisimapEntry_Copyout(
d
=
AppendOnlyVisimap_GetAttrNotNull
(
tuple
,
tupleDesc
,
Anum_pg_aovisimap_firstrownum
);
visiMapEntry
->
firstRowNum
=
DatumGetInt64
(
d
);
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map entry: copy out: "
"segNo %u firstRowNum "
INT64_FORMAT
,
visiMapEntry
->
segmentFileNum
,
...
...
@@ -224,7 +225,7 @@ AppendOnlyVisimapEntry_Copyout(
}
else
{
value
=
(
struct
varlena
*
)
DatumGetPointer
(
d
);
value
=
(
struct
varlena
*
)
DatumGetPointer
(
d
);
detoast_value
=
pg_detoast_datum
(
value
);
oldContext
=
MemoryContextSwitchTo
(
visiMapEntry
->
memoryContext
);
...
...
@@ -240,7 +241,8 @@ AppendOnlyVisimapEntry_Copyout(
MemoryContextSwitchTo
(
oldContext
);
if
(
detoast_value
!=
value
)
{
if
(
detoast_value
!=
value
)
{
pfree
(
detoast_value
);
detoast_value
=
NULL
;
}
...
...
@@ -264,13 +266,14 @@ void
AppendOnlyVisimapEntry_WriteData
(
AppendOnlyVisimapEntry
*
visiMapEntry
)
{
int
bitmapSize
,
compressedBitmapSize
;
int
bitmapSize
,
compressedBitmapSize
;
Assert
(
visiMapEntry
);
Assert
(
CurrentMemoryContext
==
visiMapEntry
->
memoryContext
);
Assert
(
AppendOnlyVisimapEntry_IsValid
(
visiMapEntry
));
bitmapSize
=
(
visiMapEntry
->
bitmap
?
(
visiMapEntry
->
bitmap
->
nwords
*
sizeof
(
uint32
))
:
0
);
bitmapSize
=
(
visiMapEntry
->
bitmap
?
(
visiMapEntry
->
bitmap
->
nwords
*
sizeof
(
uint32
))
:
0
);
bitmapSize
+=
BITMAP_COMPRESSION_HEADER_SIZE
;
Assert
(
visiMapEntry
->
data
);
...
...
@@ -288,6 +291,7 @@ AppendOnlyVisimapEntry_WriteData(
offsetof
(
AppendOnlyVisimapData
,
data
)
+
compressedBitmapSize
);
}
/**
* Persist the entry information to heap tuple value/nulls.
* Should only be called after a call to AppendOnlyVisimapEntry_copyout
...
...
@@ -299,8 +303,8 @@ AppendOnlyVisimapEntry_WriteData(
void
AppendOnlyVisimapEntry_Write
(
AppendOnlyVisimapEntry
*
visiMapEntry
,
Datum
*
values
,
bool
*
nulls
)
Datum
*
values
,
bool
*
nulls
)
{
MemoryContext
oldContext
;
...
...
@@ -309,7 +313,7 @@ AppendOnlyVisimapEntry_Write(
Assert
(
nulls
);
Assert
(
AppendOnlyVisimapEntry_IsValid
(
visiMapEntry
));
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map entry: write (segno, firstRowNum) = "
"(%d, "
INT64_FORMAT
")"
,
visiMapEntry
->
segmentFileNum
,
visiMapEntry
->
firstRowNum
);
...
...
@@ -360,7 +364,7 @@ static void
AppendOnlyVisimapEntry_GetRownumOffset
(
AppendOnlyVisimapEntry
*
visiMapEntry
,
int64
rowNum
,
int64
*
rowNumOffset
)
int64
*
rowNumOffset
)
{
Assert
(
visiMapEntry
);
Assert
(
rowNum
>=
0
);
...
...
@@ -414,7 +418,7 @@ AppendOnlyVisimapEntry_GetFirstRowNum(
AppendOnlyVisimapEntry
*
visiMapEntry
,
AOTupleId
*
tupleId
)
{
(
void
)
visiMapEntry
;
(
void
)
visiMapEntry
;
int
rowNum
;
rowNum
=
AOTupleIdGet_rowNum
(
tupleId
);
...
...
@@ -437,7 +441,8 @@ AppendOnlyVisimapEntry_IsVisible(
AppendOnlyVisimapEntry
*
visiMapEntry
,
AOTupleId
*
tupleId
)
{
int64
rowNum
,
rowNumOffset
;
int64
rowNum
,
rowNumOffset
;
bool
visibilityBit
;
Assert
(
visiMapEntry
);
...
...
@@ -471,7 +476,7 @@ AppendOnlyVisimapEntry_IsVisible(
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map entry: (firstRowNum, rowNum, visible) = "
"("
INT64_FORMAT
", "
INT64_FORMAT
", %d)"
,
visiMapEntry
->
firstRowNum
,
rowNum
,
(
int
)
visibilityBit
);
visiMapEntry
->
firstRowNum
,
rowNum
,
(
int
)
visibilityBit
);
return
visibilityBit
;
}
...
...
@@ -513,7 +518,8 @@ AppendOnlyVisimapEntry_HideTuple(
AppendOnlyVisimapEntry
*
visiMapEntry
,
AOTupleId
*
tupleId
)
{
int64
rowNum
,
rowNumOffset
;
int64
rowNum
,
rowNumOffset
;
MemoryContext
oldContext
;
HTSU_Result
result
;
...
...
@@ -524,7 +530,7 @@ AppendOnlyVisimapEntry_HideTuple(
rowNum
=
AOTupleIdGet_rowNum
(
tupleId
);
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map entry: Hide tuple: "
"firstRowNum "
INT64_FORMAT
", rowNum "
INT64_FORMAT
,
visiMapEntry
->
firstRowNum
,
rowNum
);
...
...
@@ -536,8 +542,10 @@ AppendOnlyVisimapEntry_HideTuple(
oldContext
=
MemoryContextSwitchTo
(
visiMapEntry
->
memoryContext
);
/* enlarge the bitmap by a power of two.
* this avoids the O(n*n) resizing policy of the original bitmap set */
/*
* enlarge the bitmap by a power of two. this avoids the O(n*n) resizing
* policy of the original bitmap set
*/
if
(
!
bms_covers_member
(
visiMapEntry
->
bitmap
,
rowNumOffset
))
visiMapEntry
->
bitmap
=
bms_resize
(
visiMapEntry
->
bitmap
,
...
...
@@ -597,7 +605,8 @@ AppendOnlyVisimapEntry_GetNextInvisible(
AppendOnlyVisimapEntry
*
visiMapEntry
,
AOTupleId
*
tupleId
)
{
int64
currentBitmapOffset
,
rowNum
;
int64
currentBitmapOffset
,
rowNum
;
int
offset
;
Assert
(
visiMapEntry
);
...
...
@@ -634,4 +643,3 @@ AppendOnlyVisimapEntry_GetNextInvisible(
return
false
;
}
}
src/backend/access/appendonly/appendonly_visimap_store.c
浏览文件 @
2ec69545
...
...
@@ -83,7 +83,7 @@ AppendOnlyVisimapStore_Init(
visiMapStore
->
scanKeys
=
palloc0
(
sizeof
(
ScanKeyData
)
*
APPENDONLY_VISIMAP_INDEX_SCAN_KEY_NUM
);
/
/ scan key: segno
/
* scan key: segno */
scanKey
=
visiMapStore
->
scanKeys
;
ScanKeyInit
(
scanKey
,
Anum_pg_aovisimap_segno
,
/* segno */
...
...
@@ -91,7 +91,7 @@ AppendOnlyVisimapStore_Init(
F_INT4EQ
,
0
);
/
/ scan key: firstRowNum
/
* scan key: firstRowNum */
scanKey
++
;
ScanKeyInit
(
scanKey
,
Anum_pg_aovisimap_firstrownum
,
/* attribute number to scan */
...
...
@@ -113,8 +113,8 @@ AppendOnlyVisimapStore_Init(
*/
void
AppendOnlyVisimapStore_Store
(
AppendOnlyVisimapStore
*
visiMapStore
,
AppendOnlyVisimapEntry
*
visiMapEntry
)
AppendOnlyVisimapStore
*
visiMapStore
,
AppendOnlyVisimapEntry
*
visiMapEntry
)
{
MemoryContext
oldContext
;
Relation
visimapRelation
;
...
...
@@ -126,7 +126,7 @@ AppendOnlyVisimapStore_Store(
Assert
(
visiMapStore
);
Assert
(
visiMapEntry
);
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map store: Store visimap entry: "
"(segFileNum, firstRowNum) = (%u, "
INT64_FORMAT
")"
,
visiMapEntry
->
segmentFileNum
,
visiMapEntry
->
firstRowNum
);
...
...
@@ -143,9 +143,9 @@ AppendOnlyVisimapStore_Store(
nulls
);
/*
* Write out the visimap entry to the relation.
*
If this visimap entry already in the relation, we update
*
the row. Otherwise, a new row is
inserted.
* Write out the visimap entry to the relation.
If this visimap entry
*
already in the relation, we update the row. Otherwise, a new row is
* inserted.
*/
if
(
ItemPointerIsValid
(
&
visiMapEntry
->
tupleTid
))
{
...
...
@@ -162,7 +162,7 @@ AppendOnlyVisimapStore_Store(
MemoryContextSwitchTo
(
oldContext
);
/
/ Invalidate the data after storing it.
/
* Invalidate the data after storing it. */
ItemPointerSetInvalid
(
&
visiMapEntry
->
tupleTid
);
}
...
...
@@ -182,10 +182,10 @@ AppendOnlyVisimapStore_Store(
*/
bool
AppendOnlyVisimapStore_Find
(
AppendOnlyVisimapStore
*
visiMapStore
,
AppendOnlyVisimapStore
*
visiMapStore
,
int32
segmentFileNum
,
int64
firstRowNum
,
AppendOnlyVisimapEntry
*
visiMapEntry
)
AppendOnlyVisimapEntry
*
visiMapEntry
)
{
ScanKey
scanKeys
;
IndexScanDesc
indexScan
;
...
...
@@ -195,7 +195,7 @@ AppendOnlyVisimapStore_Find(
Assert
(
RelationIsValid
(
visiMapStore
->
visimapRelation
));
Assert
(
RelationIsValid
(
visiMapStore
->
visimapIndex
));
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
elogif
(
Debug_appendonly_print_visimap
,
LOG
,
"Append-only visi map store: Load entry: "
"(segFileNum, firstRowNum) = (%u, "
INT64_FORMAT
")"
,
segmentFileNum
,
firstRowNum
);
...
...
@@ -221,7 +221,7 @@ AppendOnlyVisimapStore_Find(
"(segFileNum, firstRowNum) = (%u, "
INT64_FORMAT
")"
,
segmentFileNum
,
firstRowNum
);
/
/ failed to lookup row
/
* failed to lookup row */
AppendOnlyVisimapStore_EndScan
(
visiMapStore
,
indexScan
);
return
false
;
}
...
...
@@ -266,7 +266,7 @@ AppendOnlyVisimapStore_GetNext(
AppendOnlyVisimapStore
*
visiMapStore
,
IndexScanDesc
indexScan
,
ScanDirection
scanDirection
,
AppendOnlyVisimapEntry
*
visiMapEntry
,
AppendOnlyVisimapEntry
*
visiMapEntry
,
ItemPointerData
*
tupleTid
)
{
HeapTuple
tuple
;
...
...
@@ -444,4 +444,3 @@ AppendOnlyVisimapStore_EndScan(
index_endscan
(
indexScan
);
}
src/backend/access/appendonly/appendonly_visimap_udf.c
浏览文件 @
2ec69545
...
...
@@ -24,10 +24,8 @@
#include "utils/builtins.h"
extern
Datum
gp_aovisimap
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap_name
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap_name
(
PG_FUNCTION_ARGS
);
static
Datum
gp_aovisimap_internal
(
PG_FUNCTION_ARGS
,
Oid
aoRelOid
)
...
...
@@ -57,8 +55,7 @@ gp_aovisimap_internal(PG_FUNCTION_ARGS, Oid aoRelOid)
funcctx
=
SRF_FIRSTCALL_INIT
();
/*
* switch to memory context appropriate for multiple function
* calls
* switch to memory context appropriate for multiple function calls
*/
oldcontext
=
MemoryContextSwitchTo
(
funcctx
->
multi_call_memory_ctx
);
...
...
@@ -112,7 +109,7 @@ gp_aovisimap_internal(PG_FUNCTION_ARGS, Oid aoRelOid)
}
MemSet
(
values
,
0
,
sizeof
(
values
));
MemSet
(
nulls
,
false
,
sizeof
(
nulls
));
values
[
0
]
=
ItemPointerGetDatum
((
ItemPointer
)
&
context
->
aoTupleId
);
values
[
0
]
=
ItemPointerGetDatum
((
ItemPointer
)
&
context
->
aoTupleId
);
values
[
1
]
=
Int32GetDatum
(
AOTupleIdGet_segmentFileNum
(
&
context
->
aoTupleId
));
values
[
2
]
=
Int64GetDatum
(
AOTupleIdGet_rowNum
(
&
context
->
aoTupleId
));
...
...
@@ -152,10 +149,8 @@ gp_aovisimap_name(PG_FUNCTION_ARGS)
}
extern
Datum
gp_aovisimap_hidden_info
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap_hidden_info_name
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap_hidden_info
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap_hidden_info_name
(
PG_FUNCTION_ARGS
);
static
Datum
gp_aovisimap_hidden_info_internal
(
PG_FUNCTION_ARGS
,
Oid
aoRelOid
)
...
...
@@ -190,8 +185,7 @@ gp_aovisimap_hidden_info_internal(PG_FUNCTION_ARGS, Oid aoRelOid)
funcctx
=
SRF_FIRSTCALL_INIT
();
/*
* switch to memory context appropriate for multiple function
* calls
* switch to memory context appropriate for multiple function calls
*/
oldcontext
=
MemoryContextSwitchTo
(
funcctx
->
multi_call_memory_ctx
);
...
...
@@ -253,15 +247,18 @@ gp_aovisimap_hidden_info_internal(PG_FUNCTION_ARGS, Oid aoRelOid)
{
int64
tupcount
;
int
segno
;
if
(
context
->
appendonlySegfileInfo
)
{
FileSegInfo
*
fsinfo
=
context
->
appendonlySegfileInfo
[
context
->
i
];
tupcount
=
fsinfo
->
total_tupcount
;
segno
=
fsinfo
->
segno
;
}
else
if
(
context
->
aocsSegfileInfo
)
{
AOCSFileSegInfo
*
fsinfo
=
context
->
aocsSegfileInfo
[
context
->
i
];
tupcount
=
fsinfo
->
total_tupcount
;
segno
=
fsinfo
->
segno
;
}
...
...
@@ -309,6 +306,7 @@ Datum
gp_aovisimap_hidden_info
(
PG_FUNCTION_ARGS
)
{
Oid
aoRelOid
=
PG_GETARG_OID
(
0
);
return
gp_aovisimap_hidden_info_internal
(
fcinfo
,
aoRelOid
);
}
...
...
@@ -325,13 +323,11 @@ gp_aovisimap_hidden_info_name(PG_FUNCTION_ARGS)
return
gp_aovisimap_hidden_info_internal
(
fcinfo
,
relid
);
}
extern
Datum
gp_aovisimap_entry
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap_entry_name
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap_entry
(
PG_FUNCTION_ARGS
);
extern
Datum
gp_aovisimap_entry_name
(
PG_FUNCTION_ARGS
);
static
void
gp_aovisimap_encode_bitmap
(
char
*
bitmapBuffer
,
Bitmapset
*
bms
)
gp_aovisimap_encode_bitmap
(
char
*
bitmapBuffer
,
Bitmapset
*
bms
)
{
int
i
;
int
last
=
-
1
;
...
...
@@ -383,8 +379,7 @@ gp_aovisimap_entry_internal(PG_FUNCTION_ARGS, Oid aoRelOid)
funcctx
=
SRF_FIRSTCALL_INIT
();
/*
* switch to memory context appropriate for multiple function
* calls
* switch to memory context appropriate for multiple function calls
*/
oldcontext
=
MemoryContextSwitchTo
(
funcctx
->
multi_call_memory_ctx
);
...
...
@@ -447,7 +442,7 @@ gp_aovisimap_entry_internal(PG_FUNCTION_ARGS, Oid aoRelOid)
values
[
0
]
=
Int32GetDatum
(
visimapEntry
->
segmentFileNum
);
values
[
1
]
=
Int64GetDatum
(
visimapEntry
->
firstRowNum
);
values
[
2
]
=
Int32GetDatum
(
(
int32
)
AppendOnlyVisimapEntry_GetHiddenTupleCount
(
visimapEntry
));
(
int32
)
AppendOnlyVisimapEntry_GetHiddenTupleCount
(
visimapEntry
));
gp_aovisimap_encode_bitmap
(
VARDATA
(
context
->
bitmapBuffer
),
visimapEntry
->
bitmap
);
...
...
@@ -476,6 +471,7 @@ Datum
gp_aovisimap_entry
(
PG_FUNCTION_ARGS
)
{
Oid
aoRelOid
=
PG_GETARG_OID
(
0
);
return
gp_aovisimap_entry_internal
(
fcinfo
,
aoRelOid
);
}
...
...
src/backend/access/appendonly/appendonlyam.c
浏览文件 @
2ec69545
...
...
@@ -1763,7 +1763,7 @@ appendonly_beginrangescan(Relation relation,
for
(
i
=
0
;
i
<
segfile_count
;
i
++
)
{
seginfo
[
i
]
=
GetFileSegInfo
(
relation
,
appendOnlyMetaDataSnapshot
,
seginfo
[
i
]
=
GetFileSegInfo
(
relation
,
appendOnlyMetaDataSnapshot
,
segfile_no_arr
[
i
]);
}
return
appendonly_beginrangescan_internal
(
relation
,
...
...
src/backend/access/appendonly/appendonlyblockdirectory.c
浏览文件 @
2ec69545
...
...
@@ -29,7 +29,8 @@
int
gp_blockdirectory_entry_min_range
=
0
;
int
gp_blockdirectory_minipage_size
=
NUM_MINIPAGE_ENTRIES
;
static
inline
uint32
minipage_size
(
uint32
nEntry
)
static
inline
uint32
minipage_size
(
uint32
nEntry
)
{
return
offsetof
(
Minipage
,
entry
)
+
sizeof
(
MinipageEntry
)
*
nEntry
;
...
...
@@ -55,8 +56,7 @@ static void extract_minipage(
static
void
write_minipage
(
AppendOnlyBlockDirectory
*
blockDirectory
,
int
columnGroupNo
,
MinipagePerColumnGroup
*
minipageInfo
);
static
bool
insert_new_entry
(
AppendOnlyBlockDirectory
*
blockDirectory
,
static
bool
insert_new_entry
(
AppendOnlyBlockDirectory
*
blockDirectory
,
int
columnGroupNo
,
int64
firstRowNum
,
int64
fileOffset
,
...
...
@@ -148,6 +148,7 @@ init_internal(AppendOnlyBlockDirectory *blockDirectory)
}
MinipagePerColumnGroup
*
minipageInfo
=
&
blockDirectory
->
minipages
[
groupNo
];
minipageInfo
->
minipage
=
palloc0
(
minipage_size
(
NUM_MINIPAGE_ENTRIES
));
minipageInfo
->
numMinipageEntries
=
0
;
...
...
@@ -279,7 +280,7 @@ AppendOnlyBlockDirectory_Init_forInsert(
/*
* Load the last minipages from the block directory relation.
*/
for
(
groupNo
=
0
;
groupNo
<
blockDirectory
->
numColumnGroups
;
groupNo
++
)
for
(
groupNo
=
0
;
groupNo
<
blockDirectory
->
numColumnGroups
;
groupNo
++
)
{
load_last_minipage
(
blockDirectory
,
lastSequence
,
groupNo
);
}
...
...
@@ -324,10 +325,10 @@ AppendOnlyBlockDirectory_Init_addCol(
/*
* TODO: refactor the *_addCol* interface so that opening of
* blockdirectory relation and index, init_internal and
* c
orresponding cleanup in *_End_addCol() is called only once
*
during the add-column operation. Currently, this is being
*
called for every appendonly
segment.
* blockdirectory relation and index, init_internal and
corresponding
* c
leanup in *_End_addCol() is called only once during the add-column
*
operation. Currently, this is being called for every appendonly
* segment.
*/
blockDirectory
->
blkdirRel
=
heap_open
(
aoRel
->
rd_appendonly
->
blkdirrelid
,
RowExclusiveLock
);
...
...
@@ -354,18 +355,18 @@ set_directoryentry_range(
MinipageEntry
*
entry
;
MinipageEntry
*
next_entry
=
NULL
;
Assert
(
entry_no
>=
0
&&
((
uint32
)
entry_no
)
<
minipageInfo
->
numMinipageEntries
);
Assert
(
entry_no
>=
0
&&
((
uint32
)
entry_no
)
<
minipageInfo
->
numMinipageEntries
);
fsInfo
=
blockDirectory
->
currentSegmentFileInfo
;
Assert
(
fsInfo
!=
NULL
);
if
(
blockDirectory
->
isAOCol
)
{
aocsFsInfo
=
(
AOCSFileSegInfo
*
)
fsInfo
;
aocsFsInfo
=
(
AOCSFileSegInfo
*
)
fsInfo
;
}
entry
=
&
(
minipageInfo
->
minipage
->
entry
[
entry_no
]);
if
(((
uint32
)
entry_no
)
<
minipageInfo
->
numMinipageEntries
-
1
)
if
(((
uint32
)
entry_no
)
<
minipageInfo
->
numMinipageEntries
-
1
)
{
next_entry
=
&
(
minipageInfo
->
minipage
->
entry
[
entry_no
+
1
]);
}
...
...
@@ -393,14 +394,15 @@ set_directoryentry_range(
directoryEntry
->
range
.
lastRowNum
=
entry
->
firstRowNum
+
entry
->
rowCount
-
1
;
if
(
next_entry
==
NULL
&&
gp_blockdirectory_entry_min_range
!=
0
)
{
directoryEntry
->
range
.
lastRowNum
=
(
~
(((
int64
)
1
)
<<
63
));
/* set to the maximal value */
directoryEntry
->
range
.
lastRowNum
=
(
~
(((
int64
)
1
)
<<
63
));
/* set to the maximal
* value */
}
/*
* When crashes during inserts, or cancellation during inserts,
*
the block directory may contain out-of-date entries. W
e
*
check for the end of file here. If the requested directory entry
*
is after the end of file, return
false.
* When crashes during inserts, or cancellation during inserts,
the block
*
directory may contain out-of-date entries. We check for the end of fil
e
*
here. If the requested directory entry is after the end of file, return
* false.
*/
if
((
!
blockDirectory
->
isAOCol
&&
directoryEntry
->
range
.
fileOffset
>
fsInfo
->
eof
)
||
...
...
@@ -488,10 +490,10 @@ AppendOnlyBlockDirectory_GetEntry(
/*
* If the segment file number is the same as
* blockDirectory->currentSegmentFileNum, the in-memory minipage
*
may contain such an entry. We search the in-memory minipage
*
first. If such an entry can not be found, we search for the
*
appropriate minipage by
using the block directory btree index.
* blockDirectory->currentSegmentFileNum, the in-memory minipage
may
*
contain such an entry. We search the in-memory minipage first. If such
*
an entry can not be found, we search for the appropriate minipage by
* using the block directory btree index.
*/
if
(
segmentFileNum
==
blockDirectory
->
currentSegmentFileNum
&&
minipageInfo
->
numMinipageEntries
>
0
)
...
...
@@ -500,11 +502,12 @@ AppendOnlyBlockDirectory_GetEntry(
MinipageEntry
*
firstentry
=
&
minipageInfo
->
minipage
->
entry
[
0
];
if
(
rowNum
>=
firstentry
->
firstRowNum
)
{
/*
* Check if the existing minipage contains the requested
*
rowNum.
If so, just get it.
* Check if the existing minipage contains the requested
rowNum.
* If so, just get it.
*/
entry_no
=
find_minipage_entry
(
minipageInfo
->
minipage
,
minipageInfo
->
numMinipageEntries
,
...
...
@@ -519,11 +522,11 @@ AppendOnlyBlockDirectory_GetEntry(
}
/*
* The given rowNum may point to a tuple that does not exist
*
in the AO table any more, either because of cancellation of
*
an insert, or due to crashes during an insert. If this is
*
the case, rowNum is smaller than the highest entry in
*
the in-memory
minipage entry.
* The given rowNum may point to a tuple that does not exist
in
*
the AO table any more, either because of cancellation of an
*
insert, or due to crashes during an insert. If this is the
*
case, rowNum is smaller than the highest entry in the in-memory
* minipage entry.
*/
else
{
...
...
@@ -543,16 +546,16 @@ AppendOnlyBlockDirectory_GetEntry(
if
(
!
blockDirectory
->
isAOCol
&&
segmentFileNum
==
fsInfo
->
segno
)
break
;
else
if
(
blockDirectory
->
isAOCol
&&
segmentFileNum
==
((
AOCSFileSegInfo
*
)
fsInfo
)
->
segno
)
((
AOCSFileSegInfo
*
)
fsInfo
)
->
segno
)
break
;
}
Assert
(
fsInfo
!=
NULL
);
/*
* Search the btree index to find the minipage that contains
*
the rowNum. We find the minipages for all column groups, since
*
currently we will
need to access all columns at the same time.
* Search the btree index to find the minipage that contains
the rowNum.
*
We find the minipages for all column groups, since currently we will
* need to access all columns at the same time.
*/
heapTupleDesc
=
RelationGetDescr
(
blkdirRel
);
...
...
@@ -580,14 +583,13 @@ AppendOnlyBlockDirectory_GetEntry(
if
(
tuple
!=
NULL
)
{
/*
* MPP-17061: we need to update currentSegmentFileNum
* & currentSegmentFileInfo at the same time when we
* load the minipage for the block directory entry we
* found, otherwise we would risk having inconsistency
* between currentSegmentFileNum/currentSegmentFileInfo
* and minipage contents, which would cause wrong block
* header offset being returned in following block
* directory entry look up.
* MPP-17061: we need to update currentSegmentFileNum &
* currentSegmentFileInfo at the same time when we load the
* minipage for the block directory entry we found, otherwise we
* would risk having inconsistency between
* currentSegmentFileNum/currentSegmentFileInfo and minipage
* contents, which would cause wrong block header offset being
* returned in following block directory entry look up.
*/
blockDirectory
->
currentSegmentFileNum
=
segmentFileNum
;
blockDirectory
->
currentSegmentFileInfo
=
fsInfo
;
...
...
@@ -609,11 +611,12 @@ AppendOnlyBlockDirectory_GetEntry(
{
MinipagePerColumnGroup
*
minipageInfo
;
minipageInfo
=
&
blockDirectory
->
minipages
[
columnGroupNo
];
/*
* Perform a binary search over the minipage to find
* the
entry about the
AO block.
* Perform a binary search over the minipage to find
the entry about
* the AO block.
*/
entry_no
=
find_minipage_entry
(
minipageInfo
->
minipage
,
minipageInfo
->
numMinipageEntries
,
...
...
@@ -709,7 +712,7 @@ insert_new_entry(
blockDirectory
->
numColumnGroups
;
Assert
((
numExistingCols
>=
0
)
&&
(
numExistingCols
-
1
<
columnGroupNo
));
minipageIndex
=
columnGroupNo
-
numExistingCols
;
minipageIndex
=
columnGroupNo
-
numExistingCols
;
}
else
{
...
...
@@ -717,7 +720,7 @@ insert_new_entry(
}
minipageInfo
=
&
blockDirectory
->
minipages
[
minipageIndex
];
Assert
(
minipageInfo
->
numMinipageEntries
<=
(
uint32
)
NUM_MINIPAGE_ENTRIES
);
Assert
(
minipageInfo
->
numMinipageEntries
<=
(
uint32
)
NUM_MINIPAGE_ENTRIES
);
lastEntryNo
=
minipageInfo
->
numMinipageEntries
-
1
;
if
(
lastEntryNo
>=
0
)
...
...
@@ -748,7 +751,7 @@ insert_new_entry(
entry
->
rowCount
=
firstRowNum
-
entry
->
firstRowNum
;
}
if
(
minipageInfo
->
numMinipageEntries
>=
(
uint32
)
gp_blockdirectory_minipage_size
)
if
(
minipageInfo
->
numMinipageEntries
>=
(
uint32
)
gp_blockdirectory_minipage_size
)
{
write_minipage
(
blockDirectory
,
columnGroupNo
,
minipageInfo
);
...
...
@@ -763,7 +766,7 @@ insert_new_entry(
minipageInfo
->
numMinipageEntries
=
0
;
}
Assert
(
minipageInfo
->
numMinipageEntries
<
(
uint32
)
gp_blockdirectory_minipage_size
);
Assert
(
minipageInfo
->
numMinipageEntries
<
(
uint32
)
gp_blockdirectory_minipage_size
);
entry
=
&
(
minipageInfo
->
minipage
->
entry
[
minipageInfo
->
numMinipageEntries
]);
entry
->
firstRowNum
=
firstRowNum
;
...
...
@@ -801,6 +804,7 @@ AppendOnlyBlockDirectory_DeleteSegmentFile(Relation aoRel,
Relation
blkdirIdx
=
index_open
(
aoRel
->
rd_appendonly
->
blkdiridxid
,
RowExclusiveLock
);
ScanKeyData
scanKey
;
ScanKeyInit
(
&
scanKey
,
1
,
/* segno */
BTEqualStrategyNumber
,
...
...
@@ -815,6 +819,7 @@ AppendOnlyBlockDirectory_DeleteSegmentFile(Relation aoRel,
&
scanKey
);
HeapTuple
tuple
=
NULL
;
while
((
tuple
=
index_getnext
(
indexScan
,
ForwardScanDirection
))
!=
NULL
)
{
simple_heap_delete
(
blkdirRel
,
...
...
@@ -841,9 +846,9 @@ init_scankeys(TupleDesc tupleDesc,
Assert
(
nkeys
<=
tupleDesc
->
natts
);
for
(
keyNo
=
0
;
keyNo
<
nkeys
;
keyNo
++
)
for
(
keyNo
=
0
;
keyNo
<
nkeys
;
keyNo
++
)
{
ScanKey
scanKey
=
(
ScanKey
)(((
char
*
)
scanKeys
)
+
ScanKey
scanKey
=
(
ScanKey
)
(((
char
*
)
scanKeys
)
+
keyNo
*
sizeof
(
ScanKeyData
));
RegProcedure
opfuncid
;
StrategyNumber
strategyNumber
=
strategyNumbers
[
keyNo
];
...
...
@@ -865,7 +870,8 @@ init_scankeys(TupleDesc tupleDesc,
}
else
{
Oid
gtOid
,
leOid
;
Oid
gtOid
,
leOid
;
gtOid
=
reverse_ordering_oper_opid
(
tupleDesc
->
attrs
[
keyNo
]
->
atttypid
);
leOid
=
get_negator
(
gtOid
);
...
...
@@ -901,7 +907,7 @@ copy_out_minipage(MinipagePerColumnGroup *minipageInfo,
value
=
(
struct
varlena
*
)
DatumGetPointer
(
minipage_value
);
detoast_value
=
pg_detoast_datum
(
value
);
Assert
(
VARSIZE
(
detoast_value
)
<=
minipage_size
(
NUM_MINIPAGE_ENTRIES
));
Assert
(
VARSIZE
(
detoast_value
)
<=
minipage_size
(
NUM_MINIPAGE_ENTRIES
));
memcpy
(
minipageInfo
->
minipage
,
detoast_value
,
VARSIZE
(
detoast_value
));
if
(
detoast_value
!=
value
)
...
...
@@ -931,7 +937,9 @@ extract_minipage(AppendOnlyBlockDirectory *blockDirectory,
&
blockDirectory
->
minipages
[
columnGroupNo
];
FileSegInfo
*
fsInfo
=
blockDirectory
->
currentSegmentFileInfo
;
int64
eof
;
int
start
,
end
,
mid
=
0
;
int
start
,
end
,
mid
=
0
;
bool
found
=
false
;
heap_deform_tuple
(
tuple
,
tupleDesc
,
values
,
nulls
);
...
...
@@ -949,15 +957,15 @@ extract_minipage(AppendOnlyBlockDirectory *blockDirectory,
ItemPointerCopy
(
&
tuple
->
t_self
,
&
minipageInfo
->
tupleTid
);
/*
* When crashes during inserts, or cancellation during inserts,
*
there are out-of-date minipage entries in the block directory.
*
We reset those
entries here.
* When crashes during inserts, or cancellation during inserts,
there are
*
out-of-date minipage entries in the block directory. We reset those
* entries here.
*/
Assert
(
fsInfo
!=
NULL
);
if
(
!
blockDirectory
->
isAOCol
)
eof
=
fsInfo
->
eof
;
else
eof
=
((
AOCSFileSegInfo
*
)
fsInfo
)
->
vpinfo
.
entry
[
columnGroupNo
].
eof
;
eof
=
((
AOCSFileSegInfo
*
)
fsInfo
)
->
vpinfo
.
entry
[
columnGroupNo
].
eof
;
start
=
0
;
end
=
minipageInfo
->
numMinipageEntries
-
1
;
...
...
@@ -1032,8 +1040,8 @@ load_last_minipage(AppendOnlyBlockDirectory *blockDirectory,
scanKeys
[
2
].
sk_argument
=
Int64GetDatum
(
lastSequence
);
/*
* Search the btree to find the entry in the block directory
* th
at contains th
e last minipage.
* Search the btree to find the entry in the block directory
that contains
* the last minipage.
*/
idxScanDesc
=
index_beginscan
(
blkdirRel
,
blkdirIdx
,
blockDirectory
->
appendOnlyMetaDataSnapshot
,
...
...
@@ -1072,7 +1080,8 @@ find_minipage_entry(Minipage *minipage,
uint32
numEntries
,
int64
rowNum
)
{
int
start_no
,
end_no
;
int
start_no
,
end_no
;
int
entry_no
;
MinipageEntry
*
entry
;
...
...
@@ -1155,9 +1164,9 @@ write_minipage(AppendOnlyBlockDirectory *blockDirectory,
NULL
);
/*
* Write out the minipage to the block directory relation.
*
If this minipage is already in the relation, we update
*
the row. Otherwise, a
new row is inserted.
* Write out the minipage to the block directory relation.
If this
*
minipage is already in the relation, we update the row. Otherwise, a
* new row is inserted.
*/
if
(
ItemPointerIsValid
(
&
minipageInfo
->
tupleTid
))
{
...
...
@@ -1317,14 +1326,14 @@ AppendOnlyBlockDirectory_End_addCol(
pfree
(
blockDirectory
->
minipages
);
pfree
(
blockDirectory
->
scanKeys
);
pfree
(
blockDirectory
->
strategyNumbers
);
/*
* We already hold transaction-scope exclusive lock on the AOCS
*
relation. Let's defer release of locks on block directory as
*
well until the end
of alter-table transaction.
* We already hold transaction-scope exclusive lock on the AOCS
relation.
*
Let's defer release of locks on block directory as well until the end
* of alter-table transaction.
*/
index_close
(
blockDirectory
->
blkdirIdx
,
NoLock
);
heap_close
(
blockDirectory
->
blkdirRel
,
NoLock
);
MemoryContextDelete
(
blockDirectory
->
memoryContext
);
}
src/backend/access/appendonly/appendonlytid.c
浏览文件 @
2ec69545
...
...
@@ -65,7 +65,7 @@ gpaotidin(PG_FUNCTION_ARGS)
errmsg
(
"invalid input syntax for type gpaotid:
\"
%s
\"
"
,
str
)));
/
/ UNDONE: Move
/
* UNDONE: Move */
#define AOTupleId_MaxSegmentFileNum 127
errno
=
0
;
...
...
@@ -85,11 +85,11 @@ gpaotidin(PG_FUNCTION_ARGS)
errmsg
(
"invalid input syntax for type gpaotid:
\"
%s
\"
"
,
str
)));
result
=
(
AOTupleId
*
)
palloc
(
sizeof
(
AOTupleId
));
result
=
(
AOTupleId
*
)
palloc
(
sizeof
(
AOTupleId
));
AOTupleIdInit_Init
(
result
);
AOTupleIdInit_segmentFileNum
(
result
,
segmentFileNum
);
AOTupleIdInit_rowNum
(
result
,
rowNum
);
AOTupleIdInit_segmentFileNum
(
result
,
segmentFileNum
);
AOTupleIdInit_rowNum
(
result
,
rowNum
);
PG_RETURN_AOTID
(
result
);
}
...
...
@@ -127,14 +127,14 @@ gpaotidrecv(PG_FUNCTION_ARGS)
int64
rowNum
;
segmentFileNum
=
pq_getmsgint
(
buf
,
sizeof
(
segmentFileNum
));
/
/ UNDONE: pg_getmsgint doesn't handle 8 byte integers...
/
* UNDONE: pg_getmsgint doesn't handle 8 byte integers... */
rowNum
=
pq_getmsgint
(
buf
,
sizeof
(
rowNum
));
result
=
(
AOTupleId
*
)
palloc
(
sizeof
(
ItemPointerData
));
result
=
(
AOTupleId
*
)
palloc
(
sizeof
(
ItemPointerData
));
AOTupleIdInit_Init
(
result
);
AOTupleIdInit_segmentFileNum
(
result
,
segmentFileNum
);
AOTupleIdInit_rowNum
(
result
,
rowNum
);
AOTupleIdInit_segmentFileNum
(
result
,
segmentFileNum
);
AOTupleIdInit_rowNum
(
result
,
rowNum
);
PG_RETURN_AOTID
(
result
);
}
...
...
@@ -155,7 +155,7 @@ gpaotidsend(PG_FUNCTION_ARGS)
pq_begintypsend
(
&
buf
);
pq_sendint
(
&
buf
,
segmentFileNum
,
sizeof
(
segmentFileNum
));
/
/ UNDONE: pq_sendint doesn't handle 8 byte integers...
/
* UNDONE: pq_sendint doesn't handle 8 byte integers... */
pq_sendint
(
&
buf
,
rowNum
,
sizeof
(
rowNum
));
PG_RETURN_BYTEA_P
(
pq_endtypsend
(
&
buf
));
}
...
...
@@ -163,7 +163,8 @@ gpaotidsend(PG_FUNCTION_ARGS)
#define MAX_AO_TUPLE_ID_BUFFER 25
static
char
AOTupleIdBuffer
[
MAX_AO_TUPLE_ID_BUFFER
];
char
*
AOTupleIdToString
(
AOTupleId
*
aoTupleId
)
char
*
AOTupleIdToString
(
AOTupleId
*
aoTupleId
)
{
int
segmentFileNum
=
AOTupleIdGet_segmentFileNum
(
aoTupleId
);
int64
rowNum
=
AOTupleIdGet_rowNum
(
aoTupleId
);
...
...
src/backend/access/appendonly/appendonlywriter.c
浏览文件 @
2ec69545
此差异已折叠。
点击以展开。
src/backend/access/appendonly/test/aomd_test.c
浏览文件 @
2ec69545
...
...
@@ -10,7 +10,7 @@ void
test__AOSegmentFilePathNameLen
(
void
**
state
)
{
RelationData
reldata
;
char
*
basepath
=
"base/21381/123"
;
char
*
basepath
=
"base/21381/123"
;
expect_any
(
relpath
,
&
rnode
);
will_return
(
relpath
,
pstrdup
(
basepath
));
...
...
@@ -23,31 +23,31 @@ test__AOSegmentFilePathNameLen(void **state)
void
test__FormatAOSegmentFileName
(
void
**
state
)
{
char
*
basepath
=
"base/21381/123"
;
char
*
basepath
=
"base/21381/123"
;
int32
fileSegNo
;
char
filepathname
[
256
];
/
/ seg 0, no columns
/
* seg 0, no columns */
FormatAOSegmentFileName
(
basepath
,
0
,
-
1
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123"
);
assert_int_equal
(
fileSegNo
,
0
);
/
/ seg 1, no columns
/
* seg 1, no columns */
FormatAOSegmentFileName
(
basepath
,
1
,
-
1
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123.1"
);
assert_int_equal
(
fileSegNo
,
1
);
/
/ seg 0, column 1
/
* seg 0, column 1 */
FormatAOSegmentFileName
(
basepath
,
0
,
1
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123.128"
);
assert_int_equal
(
fileSegNo
,
128
);
/
/ seg 1, column 1
/
* seg 1, column 1 */
FormatAOSegmentFileName
(
basepath
,
1
,
1
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123.129"
);
assert_int_equal
(
fileSegNo
,
129
);
/
/ seg 0, column 2
/
* seg 0, column 2 */
FormatAOSegmentFileName
(
basepath
,
0
,
2
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123.256"
);
assert_int_equal
(
fileSegNo
,
256
);
...
...
@@ -57,38 +57,38 @@ test__FormatAOSegmentFileName(void **state)
void
test__MakeAOSegmentFileName
(
void
**
state
)
{
char
*
basepath
=
"base/21381/123"
;
char
*
basepath
=
"base/21381/123"
;
int32
fileSegNo
;
char
filepathname
[
256
];
RelationData
reldata
;
expect_any_count
(
relpath
,
&
rnode
,
-
1
);
/
/ seg 0, no columns
/
* seg 0, no columns */
will_return
(
relpath
,
pstrdup
(
basepath
));
MakeAOSegmentFileName
(
&
reldata
,
0
,
-
1
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123"
);
assert_int_equal
(
fileSegNo
,
0
);
/
/ seg 1, no columns
/
* seg 1, no columns */
will_return
(
relpath
,
pstrdup
(
basepath
));
MakeAOSegmentFileName
(
&
reldata
,
1
,
-
1
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123.1"
);
assert_int_equal
(
fileSegNo
,
1
);
/
/ seg 0, column 1
/
* seg 0, column 1 */
will_return
(
relpath
,
pstrdup
(
basepath
));
MakeAOSegmentFileName
(
&
reldata
,
0
,
1
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123.128"
);
assert_int_equal
(
fileSegNo
,
128
);
/
/ seg 1, column 1
/
* seg 1, column 1 */
will_return
(
relpath
,
pstrdup
(
basepath
));
MakeAOSegmentFileName
(
&
reldata
,
1
,
1
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123.129"
);
assert_int_equal
(
fileSegNo
,
129
);
/
/ seg 0, column 2
/
* seg 0, column 2 */
will_return
(
relpath
,
pstrdup
(
basepath
));
MakeAOSegmentFileName
(
&
reldata
,
0
,
2
,
&
fileSegNo
,
filepathname
);
assert_string_equal
(
filepathname
,
"base/21381/123.256"
);
...
...
@@ -97,7 +97,7 @@ test__MakeAOSegmentFileName(void **state)
int
main
(
int
argc
,
char
*
argv
[])
main
(
int
argc
,
char
*
argv
[])
{
cmockery_parse_arguments
(
argc
,
argv
);
...
...
src/backend/access/appendonly/test/appendonly_visimap_test.c
浏览文件 @
2ec69545
...
...
@@ -18,6 +18,7 @@ test__AppendOnlyVisimapDelete_Finish_outoforder(void **state)
AppendOnlyVisimapDelete
visiMapDelete
;
AppendOnlyVisimap
visiMap
;
bool
found
;
visiMapDelete
.
visiMap
=
&
visiMap
;
visiMap
.
visimapEntry
.
segmentFileNum
=
2
;
visiMap
.
visimapEntry
.
firstRowNum
=
32768
;
...
...
@@ -32,9 +33,9 @@ test__AppendOnlyVisimapDelete_Finish_outoforder(void **state)
will_return
(
AppendOnlyVisimapEntry_HasChanged
,
true
);
#ifdef USE_ASSERT_CHECKING
/*
* AppendOnlyVisimap_Store calls
* Assert(AppendOnlyVisimapEntry_IsValid)
* AppendOnlyVisimap_Store calls Assert(AppendOnlyVisimapEntry_IsValid)
*/
expect_any
(
AppendOnlyVisimapEntry_IsValid
,
visiMapEntry
);
will_return
(
AppendOnlyVisimapEntry_IsValid
,
true
);
...
...
@@ -66,7 +67,7 @@ test__AppendOnlyVisimapDelete_Finish_outoforder(void **state)
int
main
(
int
argc
,
char
*
argv
[])
main
(
int
argc
,
char
*
argv
[])
{
cmockery_parse_arguments
(
argc
,
argv
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录