Quantcast
Channel: Why sqlite is allowing second process to do write operation while first process is already doing write - Stack Overflow
Viewing all articles
Browse latest Browse all 2

Why sqlite is allowing second process to do write operation while first process is already doing write

$
0
0

I have written two process code both codes are copied below , let us assume sqlitep1.c refers to p1 and sqlitep2.c refers to p2

p1 constantly reads from database file sample.db and p2 writes to database file sample.db,

I executed one instances of p2 & p3 and one instances of p1, as per sqlite documentation, two process cannot simultaneously write to sqlite.

in code sqlitep2.c i have two version, one which opens connection and do write and then close (p2) and another version which opens connection and writes to db file and blocks with while(1), As shown in second version of sqlitep2.c which is executed as p3.

I first executed p3 and then p2, As per code p3 will block after writing, at this point I assume sqlite lock is not released as the connection is not closed.

But in my result I can see p2 is able to write without getting any busy error even though p3 has not released the lock.

Note : Executed in linux machine.

sqlitep1.c

#include <stdio.h>
#include </sqlite/sqlite3.h>

int main()
{
    sqlite3_stmt *pSqlStmt = NULL;
    sqlite3 *pSqlHandle = NULL;
    int ret = SQLITE_ERROR;
    char *pcSharedPath = "sample.db";
    char* pcSqlQuery = NULL;
    char *name = NULL;
    int retry_count = 0;

    while (1)
    {
        printf ("process 1.....\n");
        printf ("-----------------------------\n\n");
            ret = SQLITE_ERROR;
        /*open connection to sqlite*/
        while (ret != SQLITE_OK) {
            printf ("process 1, open connection\n");
            ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
            if (ret != SQLITE_OK)
            {
                printf ("process 1, opening failed....\n");
                if (ret == SQLITE_BUSY)
                {
                    printf ("process 1, open connection busy error....\n");
                }
            }
            sleep(1);
        }
        printf ("process 1, database connection opened...\n");
               /* prepare query */
        ret = SQLITE_ERROR;
        pcSqlQuery = "SELECT * FROM EMP";
        while (ret != SQLITE_OK)
        {
            ret = sqlite3_prepare_v2 (pSqlHandle, pcSqlQuery, -1,  &pSqlStmt, NULL);
            if (ret == SQLITE_BUSY) {
                printf ("process 1, prepare busy error....\n");
            }
            if (ret == SQLITE_ERROR) {
                printf("SQLITE_ERROR\n");
            }
            sleep(1);
        }
        printf ("process 1, prepare success...\n");
        /* extract result from query */
        while(1)
        {
            ret = sqlite3_step (pSqlStmt);
            if (ret == SQLITE_DONE)
                break;
            if (ret != SQLITE_ROW) {
                printf("process 1, no row exists...\n");
                break;
            }
            name = sqlite3_column_text (pSqlStmt, 1);
            printf ("%s \n", name);
        }

        /* finalize */
        if (NULL != pSqlStmt)
        {
    ret = SQLITE_ERROR;
            // while (ret != SQLITE_OK) {
                ret = sqlite3_finalize (pSqlStmt);
                printf ("process 1, Finalizing %d...\n", ret);
            // }
            pSqlStmt = NULL;
        }
        /* close sqlite connection */
        ret = SQLITE_ERROR;
            retry_count = 0;
            while (ret != SQLITE_OK && retry_count != 5) {
          ret = sqlite3_close(pSqlHandle);
                printf("sqlite3_close %d...\n", ret);
                retry_count++;
            }
            retry_count=0;
        if (SQLITE_OK != ret) {
            printf ("sqlite close failed....Exiting process 1...\n");
            return 0;
        }
    }
}

first version of sqlitep2.c which does not block after write operation( no while(1))

#include <stdio.h>
#include </sqlite/sqlite3.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
    sqlite3_stmt *pSqlStmt = NULL;
    sqlite3 *pSqlHandle = NULL;
    int ret = SQLITE_ERROR;
    char *pcSharedPath = "sample.db";
    char pcSqlQuery[100] = "";
    char *name = NULL;
    int i = atoi(argv[1]);
    int retry_count = 0;

    while (1)
    {
        printf ("process 2.....\n");
        printf ("-----------------------------\n\n");
        ret = SQLITE_ERROR;
        /*open connection to sqlite*/
        while (ret != SQLITE_OK) {
            printf ("process 2, open connection\n");
            ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
            if (ret != SQLITE_OK)
            {
                printf ("process 2, opening failed %d....\n", ret);
                if (ret == SQLITE_BUSY)
                {
                    printf ("process 2, open connection busy error....\n");
                }
            }
            usleep(10*1000);
        }
        printf ("process 2, database connection opened...\n");
        sqlite3_busy_timeout(pSqlHandle, 1000);

    /* prepare query */
    ret = SQLITE_ERROR;
        char name[50];
    while (ret != SQLITE_OK && retry_count != 10)
    {
                pSqlStmt = NULL;
                sqlite3_snprintf(50, name, "\"Sachin%d\"", i);
                sqlite3_snprintf(100,pcSqlQuery, "INSERT INTO EMP VALUES (%d, %s)", i, name);
                printf ("%s\n", pcSqlQuery);
          ret = sqlite3_prepare_v2 (pSqlHandle, "INSERT INTO EMP(ID, NAME) VALUES (?1, ?2);", -1,  &pSqlStmt, NULL);
                sqlite3_bind_int(pSqlStmt, 1, i);
                sqlite3_bind_text(pSqlStmt, 2, name, -1, SQLITE_STATIC);
          if (ret == SQLITE_BUSY) {
              printf ("process 2, prepare busy error....\n");
          }
          else {
                if (ret == SQLITE_ERROR)
                {
               printf ("SQLITE_ERROR...\n");
                }
            ret = SQLITE_ERROR;
            while (ret != SQLITE_OK) {
                    ret = sqlite3_step(pSqlStmt);
                printf ("process 2, return from sqlite3_step : %d...\n", ret);
                    if (ret != SQLITE_DONE) {
                            printf ("process 2, insert error...\n");
                    } else if (ret == SQLITE_BUSY) {
                    printf("sqlite3_step busy error...\n");
                } else {
                               i++;
                        ret = SQLITE_OK;
                    }
            }
          }
                printf ("process 2, ret value of insert op %d\n ", ret);
            usleep(10*1000);
                retry_count++;
      }
      retry_count=0;
      printf ("process 2, prepare success...\n");
      /* finalize */
      if (NULL != pSqlStmt)
      {
            ret = SQLITE_ERROR;
            while (ret != SQLITE_OK) {
                ret = sqlite3_finalize (pSqlStmt);
                printf ("process 2, Finalizing %d...\n", ret);
            }
          pSqlStmt = NULL;
      }
      /* close sqlite connection */
            ret = SQLITE_ERROR;
            retry_count = 0;
        ret = sqlite3_close(pSqlHandle);
            while (ret != SQLITE_OK) {
          ret = sqlite3_close(pSqlHandle);
                printf("sqlite3_close %d...\n", ret);
                retry_count++;
            sleep(1);
            }
            retry_count=0;
            pSqlHandle = NULL;
   if (SQLITE_OK != ret) {
            printf ("sqlite close failed....Exiting process 2...\n");
            return 0;
        }
            sleep(1);
    }
}

Second version of sqlitep2.c which has a infinite block while(1) after write operation, which means it is not releasing the lock.

#include <stdio.h>
#include </sqlite/sqlite3.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
    sqlite3_stmt *pSqlStmt = NULL;
    sqlite3 *pSqlHandle = NULL;
    int ret = SQLITE_ERROR;
    char *pcSharedPath = "sample.db";
    char pcSqlQuery[100] = "";
    char *name = NULL;
    int i = atoi(argv[1]);
    int retry_count = 0;

    while (1)
    {
        printf ("process 2.....\n");
        printf ("-----------------------------\n\n");
        ret = SQLITE_ERROR;
        /*open connection to sqlite*/
        while (ret != SQLITE_OK) {
            printf ("process 2, open connection\n");
            ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
            if (ret != SQLITE_OK)
            {
                printf ("process 2, opening failed %d....\n", ret);
                if (ret == SQLITE_BUSY)
                {
                    printf ("process 2, open connection busy error....\n");
                }
            }
            usleep(10*1000);
        }
        printf ("process 2, database connection opened...\n");
        sqlite3_busy_timeout(pSqlHandle, 1000);

    /* prepare query */
    ret = SQLITE_ERROR;
        char name[50];
    while (ret != SQLITE_OK && retry_count != 10)
    {
                pSqlStmt = NULL;
                sqlite3_snprintf(50, name, "\"Sachin%d\"", i);
                sqlite3_snprintf(100,pcSqlQuery, "INSERT INTO EMP VALUES (%d, %s)", i, name);
                printf ("%s\n", pcSqlQuery);
          ret = sqlite3_prepare_v2 (pSqlHandle, "INSERT INTO EMP(ID, NAME) VALUES (?1, ?2);", -1,  &pSqlStmt, NULL);
                sqlite3_bind_int(pSqlStmt, 1, i);
                sqlite3_bind_text(pSqlStmt, 2, name, -1, SQLITE_STATIC);
          if (ret == SQLITE_BUSY) {
              printf ("process 2, prepare busy error....\n");
          }
          else {
                if (ret == SQLITE_ERROR)
                {
               printf ("SQLITE_ERROR...\n");
                }
            ret = SQLITE_ERROR;
            while (ret != SQLITE_OK) {
                    ret = sqlite3_step(pSqlStmt);
                printf ("process 2, return from sqlite3_step : %d...\n", ret);
                    if (ret != SQLITE_DONE) {
                            printf ("process 2, insert error...\n");
                    } else if (ret == SQLITE_BUSY) {
                    printf("sqlite3_step busy error...\n");
                } else {
                               i++;
                        ret = SQLITE_OK;
                    }
            }
          }
                printf ("process 2, ret value of insert op %d\n ", ret);
            usleep(10*1000);
                retry_count++;
      }
      while (1) {} // block here, DO NOT proceed further.
      retry_count=0;
      printf ("process 2, prepare success...\n");
      /* finalize */
      if (NULL != pSqlStmt)
      {
            ret = SQLITE_ERROR;
            while (ret != SQLITE_OK) {
                ret = sqlite3_finalize (pSqlStmt);
                printf ("process 2, Finalizing %d...\n", ret);
            }
          pSqlStmt = NULL;
      }
      /* close sqlite connection */
            ret = SQLITE_ERROR;
            retry_count = 0;
        ret = sqlite3_close(pSqlHandle);
            while (ret != SQLITE_OK) {
          ret = sqlite3_close(pSqlHandle);
                printf("sqlite3_close %d...\n", ret);
                retry_count++;
            sleep(1);
            }
            retry_count=0;
            pSqlHandle = NULL;
   if (SQLITE_OK != ret) {
            printf ("sqlite close failed....Exiting process 2...\n");
            return 0;
        }
            sleep(1);
    }
}

Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>
<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596344.js" async> </script>