View Issue Details

IDProjectCategoryView StatusLast Update
0008302VALENTINA SERVEREvent Shcedulerpublic2018-07-18 07:57
ReporterChris ZakrewskyAssigned ToIvan Smahin 
PriorityurgentSeverityblockReproducibilityalways
Status resolvedResolutionfixed 
PlatformINTELOSWindowsOS Version*
Product Version 
Target VersionFixed in Version8.3.x 
Summary0008302: v8.3.2 - Database Events create bogus connections to database which are subsequently blocking unregistering this database
DescriptionFollowing C code demonstrates creation of a database which becomes immune to unregistering. The reason is that VServer thinks there are active connections to it when there are none (sans bogus ones).

Removing event creation from this code cures the problem albeit in an unacceptable way.

The code lists the number of active connections to database in key processing points.

The first run completes correctly, when database is closed there are no connections.

The second and third run are weird. Something behind the scenes created bogus connections. This 'something' is event scheduler gone mad (?).

The code:


/*----------------------------------------------------------------------+
| Name: clientProbe BUGTEST |
| |
| Author: ChrisZakrewsky 06/2018 |
+---------------+---------------+---------------+---------------+------*/
Private void clientProbe
(
VDatabase dbP, /* => DB */
char *nameP /* => filter */
)
    {
    VConnection connectionP = Database_GetConnection ( dbP );
    VServer serverP = Server_New ( connectionP );
    uint32_t numDatabases = Server_GetDatabaseCount ( serverP );

    for ( uint32_t i = 1; i <= numDatabases; i++ ) // one-based index
        {
        VDatabaseInfo dbInfoP = Server_DatabaseInfo ( serverP, i );

        if ( dbInfoP )
            {
            DatabaseInfo_Refresh ( dbInfoP );

            char *dbNameP = DatabaseInfo_GetName ( dbInfoP );

            if ( dbNameP
              && 0 == strncmp ( nameP, strlwr ( dbNameP ), strlen ( nameP ) ) )
                {
                uint32_t numClients = DatabaseInfo_GetClientCount ( dbInfoP );

                printf ( "\t| DB %d: '%s' -> numClients %ld\n", i, dbNameP, numClients );
                }

            VCDK_Free ( dbNameP );
            }
        }

    Server_Free ( serverP );
    }


/*----------------------------------------------------------------------+
| Name: testClientLeakBug BUGTEST |
| |
| Author: ChrisZakrewsky 06/2018 |
+---------------+---------------+---------------+---------------+------*/
#define printError() do { if ( Database_GetErrNumber ( db ) ) printf ( "Database error 0x%x: %s\n", Database_GetErrNumber ( db ), Database_GetErrString ( db ) ); } while( 0 );

Private void testClientLeakBug
(
void
)
    {
    int cacheSize = 100*1024*1024;
    int port = 15434; // Valentina
    char *host = "localhost"; // local Windows machine
    char *user = "rvs";
    char *password = "rvs";
    char *dbName = "client_leak";

    printf ( "Initializing Valentina\n" );
    Valentina_Init ( cacheSize, "", SERVER_REPORTS_LICENCE, "" );
    Valentina_InitClient ( cacheSize );
    Valentina_InitReports ( "", SERVER_REPORTS_LICENCE, "" );
    Valentina_SetDebugLevel ( 3 );

    VConnection connection = Connection_New ( host, user, password, port, 10, SERVER_ACCESS_LICENCE );

    Connection_UseSSL ( connection );
    Connection_Open ( connection );

    if ( Connection_IsConnected ( connection ) )
        {
        VDatabase db = NULL;
        VCursor cursor = NULL;
        int status = 0, newDb = 0;

        printf ( "Connected to %s:%ld, credentials: %s %s\n", host, port, user, password );

        db = Database_NewClient ( connection );
        printError();

        printf ( "BEFORE OPEN\n" ); clientProbe ( db, dbName ); // PROBE

        if ( ! Database_IsOpen ( db ) )
            {
            Database_Open ( db, dbName );
            printError();
            
            if ( Database_GetErrNumber ( db ) )
                {
                newDb = 1;
                
                printf ( "Creating Database\n" );
                Database_Create ( db, dbName, kDscDatBlbInd, 32768, kOsWindows );
                printError();
                if ( ! Database_IsOpen ( db ) )
                    {
                    Database_Open ( db, dbName );
                    printError();
                    }
                }
            }

        if ( newDb )
            {
            printf ( "BEFORE SQL\n" ); clientProbe ( db, dbName );
        
            Database_SqlExecute ( db, "SET PROPERTY DateTimeFormat OF DATABASE TO 'kYMD'; "
                                      "SET PROPERTY DateSeparator OF DATABASE TO '-'; "
                                      "SET PROPERTY TimeSeparator OF DATABASE TO ':'; ",
                                  NULL, 0 );
            printError();

            Database_SqlExecute ( db,
                                  "CREATE TABLE EntityId ( uuid_compressed VARCHAR (20) INDEXED NOT NULL, "
                                                           " version ULONG DEFAULT 0 INDEXED NOT NULL, "
                                                         " entity_type ULONG DEFAULT 0 INDEXED NOT NULL, "
                                                         " entity_scale ULONG DEFAULT 0 INDEXED NOT NULL, "
                                                         " entity_dirty_date DATETIME DEFAULT 0 NOT NULL, "
                                                         " entity_id ULONG AUTOINCREMENT UNIQUE PRIMARY KEY INDEXED NOT NULL "
                                                           " )",
                                   NULL, 0 );
            printError();

            Database_SqlExecute ( db, "CREATE TRIGGER IF NOT EXISTS Trigger_dirty "
                                       "BEFORE INSERT ON EntityId "
                                      "FOR EACH ROW "
                                        "BEGIN "
                                            "NEW.entity_dirty_date = NOW(); "
                                        "END; ",
                                  NULL, 0 );
            printError();
            
            Database_SqlExecute ( db, "USE Master; "
                                      "SET PROPERTY DateTimeFormat OF DATABASE TO 'kYMD'; "
                                      "SET PROPERTY DateSeparator OF DATABASE TO '-'; "
                                      "SET PROPERTY TimeSeparator OF DATABASE TO ':'; "
                                        "CREATE EVENT IF NOT EXISTS TransactionCleaner_$client_leak FOR DATABASE \"client_leak\" "
                                        "ON SCHEDULE EVERY 10 SECOND "
                                        "STARTS TIMESTAMP '2018-01-01 00:00:00:000' "
                                        "COMMENT 'No comments' DO "
                                            "DELETE FROM EntityId "
                                            "WHERE entity_dirty_date > 0 "
                                                 "AND datediff ( NOW (), entity_dirty_date, 'second' ) > 9 ; ",
                                   NULL, 0 );
            printError();
            
            Database_SqlExecute ( db,
                                 "INSERT INTO EntityId ( uuid_compressed,version,entity_type,entity_scale ) VALUES ('test_uuid_1', 2, 3, 4 )",
                                   NULL, 0 );
            printError();

            Database_SqlExecute ( db,
                                 "INSERT INTO EntityId ( uuid_compressed,version,entity_type,entity_scale ) VALUES ('test_uuid_2', 3, 4, 5 )",
                                   NULL, 0 );
            printError();

            printf ( "AFTER SQL\n" ); clientProbe ( db, dbName ); // PROBE
            }
        else
            {
            printf ( "AFTER OPEN\n" ); clientProbe ( db, dbName ); // PROBE
            }


        while ( Database_IsOpen ( db ) )
            {
            Database_Close ( db );
            printError();
            }


        printf ( "AFTER CLOSE\n" );
        clientProbe ( db, dbName );

        Database_Free ( db );
        if ( Connection_IsConnected ( connection ) )
            Connection_Close ( connection );
        Connection_Free ( connection );
        }
    else
        printf ( "OOPS! CAN NOT TEST! *NOT* Connected to %s:%ld, credentials: %s %s\n", host, port, user, password );

    printf ( "Shutdown Valentina\n" );
    Valentina_ShutdownReports ();
    Valentina_ShutdownClient ();
    Valentina_Shutdown ();
    }
#undef printError

Steps To ReproduceRun this sequence:


printf ( "\n\n*** FIRST RUN: ESTABLISH DATABASE ***\n\n" );
testClientLeakBug ();

    retTime = time ( 0 ) + 15; // give some time to server for processing our event (15 seconds)
    while ( time ( 0 ) < retTime );

printf ( "\n\n*** SECOND RUN: DEMONSTRATE BUG ***\n\n" );
testClientLeakBug ();

    retTime = time ( 0 ) + 15; // give even more time to server for processing our event (15 seconds)
    while ( time ( 0 ) < retTime );

printf ( "\n\n*** THIRD RUN: DEMONSTRATE BUG ONCE MORE ***\n\n" );
testClientLeakBug ();

Additional InformationA sample output to console provided in attachment.
TagsNo tags attached.

Activities

Chris Zakrewsky

Chris Zakrewsky

2018-07-02 17:24

reporter  

Snapshot-2018-07-02-190630.png (37,353 bytes)
Chris Zakrewsky

Chris Zakrewsky

2018-07-16 12:11

reporter   ~0010267

Last edited: 2018-07-16 12:14

View 3 revisions

Do you have any problems to reproduce this, or is it just lack of time?
(I know, vacation season and all)

However I would appreciate at least an explanation why these connections are left dangling by the scheduler and what can I do about it.

As it is now, I can not unregister such database from VServer and can not subsequently open it in an off-line mode (i.e. sans server), because it instantly becomes read-only. Any hints?

Ivan Smahin

Ivan Smahin

2018-07-16 12:35

manager   ~0010268

I will fix it nearest time- today or tomorrow morning.

Issue History

Date Modified Username Field Change
2018-07-02 17:24 Chris Zakrewsky New Issue
2018-07-02 17:24 Chris Zakrewsky File Added: Snapshot-2018-07-02-190630.png
2018-07-16 12:11 Chris Zakrewsky Note Added: 0010267
2018-07-16 12:13 Chris Zakrewsky Note Edited: 0010267 View Revisions
2018-07-16 12:14 Chris Zakrewsky Note Edited: 0010267 View Revisions
2018-07-16 12:35 Ivan Smahin Note Added: 0010268
2018-07-18 07:57 Ivan Smahin Status new => resolved
2018-07-18 07:57 Ivan Smahin Fixed in Version => 8.3.x
2018-07-18 07:57 Ivan Smahin Resolution open => fixed
2018-07-18 07:57 Ivan Smahin Assigned To => Ivan Smahin