SQLite

Check-in [7baf02946e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Correct subtle timing issues in the win32lock test cases and in the lock_win32_file Tcl command. Also, eliminate superfluous MSVC compiler warnings.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | winopen-retry-logic
Files: files | file ages | folders
SHA1: 7baf02946e14eb889d864984ff3b3822aad8a3c9
User & Date: mistachkin 2011-08-02 23:34:00.968
Context
2011-08-02
23:45
Add explanatory comment to the win32lock-2.2 test case. (Closed-Leaf check-in: 4cb17881d9 user: mistachkin tags: winopen-retry-logic)
23:34
Correct subtle timing issues in the win32lock test cases and in the lock_win32_file Tcl command. Also, eliminate superfluous MSVC compiler warnings. (check-in: 7baf02946e user: mistachkin tags: winopen-retry-logic)
20:19
Fix missing info exists check for win32lock-2.2 (the one previously applied to win32lock-1.2). (check-in: 8a52698e64 user: mistachkin tags: winopen-retry-logic)
Changes
Unified Diff Ignore Whitespace Patch
Changes to Makefile.msc.
39
40
41
42
43
44
45





46
47
48
49
50
51
52

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#
TCC = $(TCC) -DNDEBUG






# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!if "$(TCLINCDIR)" == ""







>
>
>
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#
TCC = $(TCC) -DNDEBUG

#
# Prevent warnings about "insecure" runtime library functions being used.
#
TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS

# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!if "$(TCLINCDIR)" == ""
Changes to src/test1.c.
5641
5642
5643
5644
5645
5646
5647

5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662







5663
5664
5665
5666
5667
5668
5669

#if SQLITE_OS_WIN
/*
** Information passed from the main thread into the windows file locker
** background thread.
*/
struct win32FileLocker {

  HANDLE h;           /* Handle of the file to be locked */
  int delay1;         /* Delay before locking */
  int delay2;         /* Delay before unlocking */
  int ok;             /* Finished ok */
  int err;            /* True if an error occurs */
};
#endif


#if SQLITE_OS_WIN
/*
** The background thread that does file locking.
*/
static void win32_file_locker(void *pAppData){
  struct win32FileLocker *p = (struct win32FileLocker*)pAppData;







  if( p->delay1 ) Sleep(p->delay1);
  if( LockFile(p->h, 0, 0, 100000000, 0) ){
    Sleep(p->delay2);
    UnlockFile(p->h, 0, 0, 100000000, 0);
    p->ok = 1;
  }else{
    p->err = 1;







>















>
>
>
>
>
>
>







5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677

#if SQLITE_OS_WIN
/*
** Information passed from the main thread into the windows file locker
** background thread.
*/
struct win32FileLocker {
  char *evName;       /* Name of event to signal thread startup */
  HANDLE h;           /* Handle of the file to be locked */
  int delay1;         /* Delay before locking */
  int delay2;         /* Delay before unlocking */
  int ok;             /* Finished ok */
  int err;            /* True if an error occurs */
};
#endif


#if SQLITE_OS_WIN
/*
** The background thread that does file locking.
*/
static void win32_file_locker(void *pAppData){
  struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
  if( p->evName ){
    HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
    if ( ev ){
      SetEvent(ev);
      CloseHandle(ev);
    }
  }
  if( p->delay1 ) Sleep(p->delay1);
  if( LockFile(p->h, 0, 0, 100000000, 0) ){
    Sleep(p->delay2);
    UnlockFile(p->h, 0, 0, 100000000, 0);
    p->ok = 1;
  }else{
    p->err = 1;
5684
5685
5686
5687
5688
5689
5690
5691
5692

5693


5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
*/
static int win32_file_lock(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  static struct win32FileLocker x = { 0, 0, 0 };
  const char *zFilename;

  int retry = 0;


  
  if( objc!=4 && objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
    return TCL_ERROR;
  }
  if( objc==1 ){
    char zBuf[200];
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
                     x.ok, x.err, x.delay1, x.delay2, x.h);
    Tcl_AppendResult(interp, zBuf, (char*)0);
    return TCL_OK;
  }
  while( x.h && retry<30 ){
    retry++;







|

>

>
>






<







5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710

5711
5712
5713
5714
5715
5716
5717
*/
static int win32_file_lock(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
  const char *zFilename;
  char zBuf[200];
  int retry = 0;
  HANDLE ev;
  DWORD wResult;
  
  if( objc!=4 && objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
    return TCL_ERROR;
  }
  if( objc==1 ){

    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
                     x.ok, x.err, x.delay1, x.delay2, x.h);
    Tcl_AppendResult(interp, zBuf, (char*)0);
    return TCL_OK;
  }
  while( x.h && retry<30 ){
    retry++;
5716
5717
5718
5719
5720
5721
5722





5723
5724
5725







5726
5727
5728
5729
5730
5731
5732
  zFilename = Tcl_GetString(objv[1]);
  x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
              FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
              FILE_ATTRIBUTE_NORMAL, 0);
  if( !x.h ){
    Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
    return TCL_ERROR;





  }
  _beginthread(win32_file_locker, 0, (void*)&x);
  Sleep(0);







  return TCL_OK;
}
#endif


/*
**      optimization_control DB OPT BOOLEAN







>
>
>
>
>



>
>
>
>
>
>
>







5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
  zFilename = Tcl_GetString(objv[1]);
  x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
              FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
              FILE_ATTRIBUTE_NORMAL, 0);
  if( !x.h ){
    Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
    return TCL_ERROR;
  }
  ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
  if ( !ev ){
    Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
    return TCL_ERROR;
  }
  _beginthread(win32_file_locker, 0, (void*)&x);
  Sleep(0);
  if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
    sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
    Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
    CloseHandle(ev);
    return TCL_ERROR;
  }
  CloseHandle(ev);
  return TCL_OK;
}
#endif


/*
**      optimization_control DB OPT BOOLEAN
Changes to test/win32lock.test.
37
38
39
40
41
42
43
44
45
46




47
48
49

50
51

52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67

68

69
70
71
72
73
74
75
76
77


78
79
80
81

82
83

84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99

100

101
102
103
104
105
106
107
    INSERT INTO t1 VALUES(3,randomblob(25000));
    INSERT INTO t1 VALUES(4,randomblob(12500));
    SELECT x, length(y) FROM t1 ORDER BY rowid;
  }
} {1 100000 2 50000 3 25000 4 12500}

unset -nocomplain delay1 rc msg
set delay1 50
set rc 0
set old_pending_byte [sqlite3_test_control_pending_byte 0x40000000]




while {1} {
  sqlite3_sleep 10
  lock_win32_file test.db 0 $::delay1

  set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
  if {$rc} {

    do_test win32lock-1.2-$delay1-fin {
       set ::msg
    } {disk I/O error}
    break
  } else {

    do_test win32lock-1.2-$delay1 {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {[info exists ::log] && $::log!=""} {
      do_test win32lock-1.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
    incr delay1 50
  }

  set ::log {}

}

do_test win32lock-2.0 {
  file_control_win32_av_retry db -1 -1
} {0 10 25}
do_test win32lock-2.1 {
  file_control_win32_av_retry db 1 1
} {0 1 1}



set delay1 50
while {1} {
  sqlite3_sleep 10
  lock_win32_file test.db 0 $::delay1

  set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
  if {$rc} {

    do_test win32lock-2.2-$delay1-fin {
       set ::msg
    } {disk I/O error}
    break
  } else {

    do_test win32lock-2.2-$delay1 {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {[info exists ::log] && $::log!=""} {
      do_test win32lock-2.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
    incr delay1 50
  }

  set ::log {}

}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize







<
<

>
>
>
>

<

>


>
|


<

>
|








<

>
|
>









>
>
|

<

>


>
|


<

>
|








<

>
|
>







37
38
39
40
41
42
43


44
45
46
47
48
49

50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
    INSERT INTO t1 VALUES(3,randomblob(25000));
    INSERT INTO t1 VALUES(4,randomblob(12500));
    SELECT x, length(y) FROM t1 ORDER BY rowid;
  }
} {1 100000 2 50000 3 25000 4 12500}

unset -nocomplain delay1 rc msg


set old_pending_byte [sqlite3_test_control_pending_byte 0x40000000]

set win32_lock_ok [list]
set win32_lock_error [list]
set delay1 25
while {1} {

  lock_win32_file test.db 0 $::delay1
  set ::log {}
  set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
  if {$rc} {
    lappend win32_lock_error $::delay1
    do_test win32lock-1.2-$delay1-error {
       set ::msg
    } {disk I/O error}

  } else {
    lappend win32_lock_ok $::delay1
    do_test win32lock-1.2-$delay1-ok {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {[info exists ::log] && $::log!=""} {
      do_test win32lock-1.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }

  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  incr delay1 25
  sqlite3_sleep 10
}

do_test win32lock-2.0 {
  file_control_win32_av_retry db -1 -1
} {0 10 25}
do_test win32lock-2.1 {
  file_control_win32_av_retry db 1 1
} {0 1 1}

set win32_lock_ok [list]
set win32_lock_error [list]
set delay1 1
while {1} {

  lock_win32_file test.db 0 $::delay1
  set ::log {}
  set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
  if {$rc} {
    lappend win32_lock_error $::delay1
    do_test win32lock-2.2-$delay1-error {
       set ::msg
    } {disk I/O error}

  } else {
    lappend win32_lock_ok $::delay1
    do_test win32lock-2.2-$delay1-ok {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {[info exists ::log] && $::log!=""} {
      do_test win32lock-2.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }

  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  incr delay1 1
  sqlite3_sleep 10
}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize