You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Alexander Lapin (Jira)" <ji...@apache.org> on 2021/09/17 05:53:00 UTC

[jira] [Updated] (IGNITE-15396) TableManager#table(UUID) could return null value even though the required table is already created.

     [ https://issues.apache.org/jira/browse/IGNITE-15396?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Alexander Lapin updated IGNITE-15396:
-------------------------------------
    Description: 
It seems that the following code introduced by IGNITE-14970 can lead to an error if a required table already exists in the cluster but the current node has not seen this event:
{code:java}
if (tbl != null && getTblFut.complete(tbl) || getTblFut.complete(null))
    removeListener(TableEvent.CREATE, clo, null);
{code}
 

[https://github.com/apache/ignite-3/blob/main/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java#L832]

Looks like it should be something as follows:
{code:java}
if (tbl != null && getTblFut.complete(tbl) || 
    !isTableConfigured(id) && getTblFut.complete(null))
    removeListener(TableEvent.CREATE, clo, null);
{code}
 *UPD 1*

 Besides mention above it's also required to check whether table is present in meta storage, instead of just checking it locally

As-Is:

 
{code:java}
var tbl = tablesById.get(id);

if (tbl != null)
    return tbl;
{code}
To-Be:

 

 
{code:java}
if (!tableIdsConfigured().values().contains(id))
    return null;
    
var tbl = tablesById.get(id);

if (tbl != null)
    return tbl;
{code}
However proper retrieval of distributed state is not implemented yet IGNITE-15412

There's a hack solution
{code:java}
    private Map</* table name*/String, /* table id*/IgniteUuid> tableCoordinatesConfigured() {
        IgniteBiTuple<ByteArray, ByteArray> range = toRange(new ByteArray(PUBLIC_PREFIX));        var tableCoordinates = new HashMap<String, IgniteUuid>();
        String tblName = null;
        String innerTblId = null;        try (Cursor<Entry> cursor = metaStorageMgr.range(range.get1(), range.get2())) {
            while (cursor.hasNext()) {
                Entry entry = cursor.next();                List<String> keySplit = ConfigurationUtil.split(entry.key().toString());                if (keySplit.size() == 5 && NamedListNode.NAME.equals(keySplit.get(4))) {
                    @Nullable byte[] value = entry.value();
                    if (value != null) {
                        tblName = ByteUtils.fromBytes(value).toString();
                        innerTblId = keySplit.get(3);
                    }
                }                if (keySplit.size() == 5 && "id".equals(keySplit.get(4)) && keySplit.get(3).equals(innerTblId))
                    tableCoordinates.put(tblName, IgniteUuid.fromString(ByteUtils.fromBytes(entry.value()).toString()));
            }
        }
        catch (Exception e) {
            LOG.error("Can't get table names.", e);
        }        return tableCoordinates;
    }

{code}
However it's extremely horrible, so we'd better wait for IGNITE-15412

 

  was:
It seems that the following code introduced by IGNITE-14970 can lead to an error if a required table already exists in the cluster but the current node has not seen this event:
{code:java}
if (tbl != null && getTblFut.complete(tbl) || getTblFut.complete(null))
    removeListener(TableEvent.CREATE, clo, null);
{code}
 

[https://github.com/apache/ignite-3/blob/main/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java#L832]



Looks like it should be something as follows:
{code:java}
if (tbl != null && getTblFut.complete(tbl) || 
    !isTableConfigured(id) && getTblFut.complete(null))
    removeListener(TableEvent.CREATE, clo, null);
{code}
 

 


> TableManager#table(UUID) could return null value even though the required table is already created.
> ---------------------------------------------------------------------------------------------------
>
>                 Key: IGNITE-15396
>                 URL: https://issues.apache.org/jira/browse/IGNITE-15396
>             Project: Ignite
>          Issue Type: Bug
>            Reporter: Vyacheslav Koptilin
>            Priority: Major
>              Labels: ignite-3
>             Fix For: 3.0.0-alpha3
>
>
> It seems that the following code introduced by IGNITE-14970 can lead to an error if a required table already exists in the cluster but the current node has not seen this event:
> {code:java}
> if (tbl != null && getTblFut.complete(tbl) || getTblFut.complete(null))
>     removeListener(TableEvent.CREATE, clo, null);
> {code}
>  
> [https://github.com/apache/ignite-3/blob/main/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java#L832]
> Looks like it should be something as follows:
> {code:java}
> if (tbl != null && getTblFut.complete(tbl) || 
>     !isTableConfigured(id) && getTblFut.complete(null))
>     removeListener(TableEvent.CREATE, clo, null);
> {code}
>  *UPD 1*
>  Besides mention above it's also required to check whether table is present in meta storage, instead of just checking it locally
> As-Is:
>  
> {code:java}
> var tbl = tablesById.get(id);
> if (tbl != null)
>     return tbl;
> {code}
> To-Be:
>  
>  
> {code:java}
> if (!tableIdsConfigured().values().contains(id))
>     return null;
>     
> var tbl = tablesById.get(id);
> if (tbl != null)
>     return tbl;
> {code}
> However proper retrieval of distributed state is not implemented yet IGNITE-15412
> There's a hack solution
> {code:java}
>     private Map</* table name*/String, /* table id*/IgniteUuid> tableCoordinatesConfigured() {
>         IgniteBiTuple<ByteArray, ByteArray> range = toRange(new ByteArray(PUBLIC_PREFIX));        var tableCoordinates = new HashMap<String, IgniteUuid>();
>         String tblName = null;
>         String innerTblId = null;        try (Cursor<Entry> cursor = metaStorageMgr.range(range.get1(), range.get2())) {
>             while (cursor.hasNext()) {
>                 Entry entry = cursor.next();                List<String> keySplit = ConfigurationUtil.split(entry.key().toString());                if (keySplit.size() == 5 && NamedListNode.NAME.equals(keySplit.get(4))) {
>                     @Nullable byte[] value = entry.value();
>                     if (value != null) {
>                         tblName = ByteUtils.fromBytes(value).toString();
>                         innerTblId = keySplit.get(3);
>                     }
>                 }                if (keySplit.size() == 5 && "id".equals(keySplit.get(4)) && keySplit.get(3).equals(innerTblId))
>                     tableCoordinates.put(tblName, IgniteUuid.fromString(ByteUtils.fromBytes(entry.value()).toString()));
>             }
>         }
>         catch (Exception e) {
>             LOG.error("Can't get table names.", e);
>         }        return tableCoordinates;
>     }
> {code}
> However it's extremely horrible, so we'd better wait for IGNITE-15412
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)