View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0008302 | VALENTINA SERVER | Event Shceduler | public | 2018-07-02 17:24 | 2018-07-18 07:57 |
Reporter | Chris Zakrewsky | Assigned To | Ivan Smahin | ||
Priority | urgent | Severity | block | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | INTEL | OS | Windows | OS Version | * |
Fixed in Version | 8.3.x | ||||
Summary | 0008302: v8.3.2 - Database Events create bogus connections to database which are subsequently blocking unregistering this database | ||||
Description | Following 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 Reproduce | Run 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 Information | A sample output to console provided in attachment. | ||||
Tags | No tags attached. | ||||
Snapshot-2018-07-02-190630.png (37,353 bytes) |
|
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? |
|
I will fix it nearest time- today or tomorrow morning. | |
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 | |
2018-07-16 12:14 | Chris Zakrewsky | Note Edited: 0010267 | |
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 |