[
https://issues.apache.org/jira/browse/IGNITE-17428?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Mirza Aliev updated IGNITE-17428:
---------------------------------
Description:
Current version of TableManager#tableAsyncInternal can possibly not detect
table that is being created while tableAsyncInternal is called. Scenario:
- tableAsyncInternal checks tablesByIdVv.latest() and there is no table
- the table creation started, table metadata appears in meta storage
- TableEvent.CREATE is fired
- tableAsyncInternal registers a listener for TableEvent.CREATE (after it is
fired for corresponding table)
- tableAsyncInternal checks tablesByIdVv.latest() once again and there still is
no table, because the table creation is not completed
- {{!isTableConfigured(id)}} condition returns *false* as the table is present
in meta storage
- {{if (tbl != null && getTblFut.complete(tbl) || !isTableConfigured(id) &&
getTblFut.complete(null))}} evaluates *false* and the future created fot
getTable never completes.
Possibly we should use VersionedValue#whenComplete instead of creating listener
for event. The table is present in map wrapped in versioned value only when the
table creation is completed, and whenComplete allows to create a callback to
check the table presence.
The same problem is presented for {{SchemaManager}} when we get schema in
{{SchemaManager#tableSchema}}
Possible fix for {{SchemaManager}} is to use this pattern
{code:java}
registriesVv.whenComplete((token, val, e) -> {
if (schemaVer <= val.get(tblId).lastSchemaVersion()) {
fut.complete(getSchemaDescriptorLocally(schemaVer, tblCfg));
}
});
{code}
instead of creating listener for CREATE event. The same approach can be used
for {{TableManager}}
was:
Current version of TableManager#tableAsyncInternal can possibly not detect
table that is being created while tableAsyncInternal is called. Scenario:
- tableAsyncInternal checks tablesByIdVv.latest() and there is no table
- the table creation started, table metadata appears in meta storage
- TableEvent.CREATE is fired
- tableAsyncInternal registers a listener for TableEvent.CREATE (after it is
fired for corresponding table)
- tableAsyncInternal checks tablesByIdVv.latest() once again and there still is
no table, because the table creation is not completed
- {{!isTableConfigured(id)}} condition returns *false* as the table is present
in meta storage
- {{if (tbl != null && getTblFut.complete(tbl) || !isTableConfigured(id) &&
getTblFut.complete(null))}} evaluates *false* and the future created fot
getTable never completes.
Possibly we should use VersionedValue#whenComplete instead of creating listener
for event. The table is present in map wrapped in versioned value only when the
table creation is completed, and whenComplete allows to create a callback to
check the table presence.
The same problem is presented for {{SchemaManager}} when we get schema in
{{SchemaManager#tableSchema}}
> Race between creating table and getting table, between creating schema and
> getting schema
> -----------------------------------------------------------------------------------------
>
> Key: IGNITE-17428
> URL: https://issues.apache.org/jira/browse/IGNITE-17428
> Project: Ignite
> Issue Type: Bug
> Reporter: Denis Chudov
> Priority: Major
> Labels: ignite-3
>
> Current version of TableManager#tableAsyncInternal can possibly not detect
> table that is being created while tableAsyncInternal is called. Scenario:
> - tableAsyncInternal checks tablesByIdVv.latest() and there is no table
> - the table creation started, table metadata appears in meta storage
> - TableEvent.CREATE is fired
> - tableAsyncInternal registers a listener for TableEvent.CREATE (after it is
> fired for corresponding table)
> - tableAsyncInternal checks tablesByIdVv.latest() once again and there still
> is no table, because the table creation is not completed
> - {{!isTableConfigured(id)}} condition returns *false* as the table is
> present in meta storage
> - {{if (tbl != null && getTblFut.complete(tbl) || !isTableConfigured(id) &&
> getTblFut.complete(null))}} evaluates *false* and the future created fot
> getTable never completes.
> Possibly we should use VersionedValue#whenComplete instead of creating
> listener for event. The table is present in map wrapped in versioned value
> only when the table creation is completed, and whenComplete allows to create
> a callback to check the table presence.
> The same problem is presented for {{SchemaManager}} when we get schema in
> {{SchemaManager#tableSchema}}
> Possible fix for {{SchemaManager}} is to use this pattern
> {code:java}
> registriesVv.whenComplete((token, val, e) -> {
> if (schemaVer <= val.get(tblId).lastSchemaVersion()) {
> fut.complete(getSchemaDescriptorLocally(schemaVer, tblCfg));
> }
> });
> {code}
> instead of creating listener for CREATE event. The same approach can be used
> for {{TableManager}}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)