/ Check-in [7baf0294]
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 | SQL 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
Context
2011-08-02
23:45
Add explanatory comment to the win32lock-2.2 test case. Closed-Leaf check-in: 4cb17881 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: 7baf0294 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: 8a52698e user: mistachkin tags: winopen-retry-logic
Changes
Hide Diffs Unified Diffs 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
....
5656
5657
5658
5659
5660
5661
5662







5663
5664
5665
5666
5667
5668
5669
....
5684
5685
5686
5687
5688
5689
5690
5691
5692

5693


5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
....
5716
5717
5718
5719
5720
5721
5722





5723
5724
5725







5726
5727
5728
5729
5730
5731
5732

#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;
................................................................................
*/
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++;
................................................................................
  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







>







 







>
>
>
>
>
>
>







 







|

>

>
>






<







 







>
>
>
>
>



>
>
>
>
>
>
>







5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
....
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
....
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
....
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

#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;
................................................................................
*/
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++;
................................................................................
  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
108
    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
finish_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
108
109
110
111
112
113
114
115
116
    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
finish_test