1--TEST--
2Persistent connections and mysqli.max_links
3--SKIPIF--
4<?php
5    require_once('skipif.inc');
6    require_once('skipifemb.inc');
7    require_once('skipifconnectfailure.inc');
8    require_once('table.inc');
9
10    mysqli_query($link, 'DROP USER pcontest');
11    mysqli_query($link, 'DROP USER pcontest@localhost');
12
13    if (!mysqli_query($link, 'CREATE USER pcontest@"%" IDENTIFIED BY "pcontest"') ||
14        !mysqli_query($link, 'CREATE USER pcontest@localhost IDENTIFIED BY "pcontest"')) {
15        printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
16        mysqli_close($link);
17        die("skip CREATE USER failed");
18    }
19
20    // we might be able to specify the host using CURRENT_USER(), but...
21    if (!mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db)) ||
22        !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'localhost'", $db))) {
23        printf("skip Cannot GRANT SELECT to second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
24        mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
25        mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
26        mysqli_query($link, 'DROP USER pcontest@localhost');
27        mysqli_query($link, 'DROP USER pcontest');
28        mysqli_close($link);
29        die("skip GRANT failed");
30    }
31
32    if (!($link_pcontest = @my_mysqli_connect($host, 'pcontest', 'pcontest', $db, $port, $socket))) {
33        mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
34        mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
35        mysqli_query($link, 'DROP USER pcontest@localhost');
36        mysqli_query($link, 'DROP USER pcontest');
37        mysqli_close($link);
38        die("skip CONNECT using new user failed");
39    }
40    mysqli_close($link);
41?>
42--INI--
43mysqli.allow_persistent=1
44mysqli.max_persistent=2
45mysqli.rollback_on_cached_plink=1
46--FILE--
47<?php
48    require_once("connect.inc");
49    require_once('table.inc');
50
51
52    if (!mysqli_query($link, 'DROP USER pcontest') ||
53        !mysqli_query($link, 'DROP USER pcontest@localhost') ||
54        !mysqli_query($link, 'CREATE USER pcontest@"%" IDENTIFIED BY "pcontest"') ||
55        !mysqli_query($link, 'CREATE USER pcontest@localhost IDENTIFIED BY "pcontest"') ||
56        !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db)) ||
57        !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'localhost'", $db))) {
58        printf("[000] Init failed, [%d] %s\n",
59            mysqli_errno($plink), mysqli_error($plink));
60    }
61
62    var_dump(mysqli_get_links_stats(1));
63
64    echo "Before pconnect:";
65    var_dump(mysqli_get_links_stats());
66
67    if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
68        printf("[001] Cannot connect using the second DB user created during SKIPIF, [%d] %s\n",
69            mysqli_connect_errno(), mysqli_connect_error());
70
71    echo "After pconnect:";
72    var_dump(mysqli_get_links_stats());
73
74    ob_start();
75    phpinfo();
76    $phpinfo = strip_tags(ob_get_contents());
77    ob_end_clean();
78
79    $phpinfo = substr($phpinfo, strpos($phpinfo, 'MysqlI Support => enabled'), 500);
80    if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
81        printf("[002] Cannot get # active persistent links from phpinfo()\n");
82    $num_plinks = $matches[1];
83
84    if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1'))
85        printf("[003] Cannot run query on persistent connection of second DB user, [%d] %s\n",
86            mysqli_errno($plink), mysqli_error($plink));
87
88    if (!$row = mysqli_fetch_assoc($res))
89        printf("[004] Cannot run fetch result, [%d] %s\n",
90            mysqli_errno($plink), mysqli_error($plink));
91    mysqli_free_result($res);
92    var_dump($row);
93
94    // change the password for the second DB user and kill the persistent connection
95    if ((!mysqli_query($link, 'SET PASSWORD FOR pcontest = "newpass"') &&
96            !mysqli_query($link, 'SET PASSWORD FOR pcontest = PASSWORD("newpass")'))||
97            !mysqli_query($link, 'FLUSH PRIVILEGES'))
98        printf("[005] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
99
100        // change the password for the second DB user and kill the persistent connection
101    if ((!mysqli_query($link, 'SET PASSWORD FOR pcontest@localhost = "newpass"') &&
102        !mysqli_query($link, 'SET PASSWORD FOR pcontest@localhost = PASSWORD("newpass")')) ||
103            !mysqli_query($link, 'FLUSH PRIVILEGES'))
104        printf("[006] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
105
106    // persistent connections cannot be closed but only be killed
107    $pthread_id = mysqli_thread_id($plink);
108    if (!mysqli_query($link, sprintf('KILL %d', $pthread_id)))
109        printf("[007] Cannot KILL persistent connection of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
110    // give the server a second to really kill the thread
111    sleep(1);
112
113    if (!$res = mysqli_query($link, "SHOW FULL PROCESSLIST"))
114        printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
115
116    $running_threads = array();
117    while ($row = mysqli_fetch_assoc($res))
118        $running_threads[$row['Id']] = $row;
119    mysqli_free_result($res);
120
121    if (isset($running_threads[$pthread_id]))
122        printf("[009] Persistent connection has not been killed\n");
123
124    echo "Before second pconnect:";
125    var_dump(mysqli_get_links_stats());
126
127    // this fails and we have 0 (<= $num_plinks) connections
128    if ($plink = @my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
129        printf("[010] Can connect using the old password, [%d] %s\n",
130            mysqli_connect_errno($link), mysqli_connect_error($link));
131
132    echo "After second pconnect:";
133    var_dump(mysqli_get_links_stats());
134
135    ob_start();
136    phpinfo();
137    $phpinfo = strip_tags(ob_get_contents());
138    ob_end_clean();
139    $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500);
140    if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
141        printf("[010] Cannot get # of active persistent links from phpinfo()\n");
142
143    var_dump(mysqli_get_links_stats());
144
145    $num_plinks_kill = $matches[1];
146    $sstats = mysqli_get_links_stats();
147    if ($sstats['active_plinks'] != $num_plinks_kill) {
148        printf("[010.2] Num of active plinks differ %s %s\n", $sstats['active_plinks'], $num_plinks_kill);
149    }
150    if ($num_plinks_kill > $num_plinks)
151        printf("[011] Expecting Active Persistent Links < %d, got %d\n", $num_plinks, $num_plinks_kill);
152
153    if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket))
154        printf("[012] Cannot connect using the new password, [%d] %s\n",
155            mysqli_connect_errno(), mysqli_connect_error());
156
157    if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1'))
158        printf("[013] Cannot run query on persistent connection of second DB user, [%d] %s\n",
159            mysqli_errno($plink), mysqli_error($plink));
160
161    if (!$row = mysqli_fetch_assoc($res))
162        printf("[014] Cannot run fetch result, [%d] %s\n",
163            mysqli_errno($plink), mysqli_error($plink));
164    mysqli_free_result($res);
165    var_dump($row);
166
167    if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) {
168        printf("[015] Can open more persistent connections than allowed, [%d] %s\n",
169            mysqli_connect_errno(), mysqli_connect_error());
170        var_dump(mysqli_get_links_stats());
171    }
172
173    ob_start();
174    phpinfo();
175    $phpinfo = strip_tags(ob_get_contents());
176    ob_end_clean();
177    $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500);
178    if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
179        printf("[016] Cannot get # of active persistent links from phpinfo()\n");
180
181    $num_plinks = $matches[1];
182    if ($num_plinks > (int)ini_get('mysqli.max_persistent'))
183        printf("[017] mysqli.max_persistent=%d allows %d open connections!\n", ini_get('mysqli.max_persistent'),$num_plinks);
184
185    mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
186    mysqli_query($link, 'DROP USER pcontest');
187    mysqli_close($link);
188    print "done!";
189?>
190--CLEAN--
191<?php
192require_once("connect.inc");
193if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
194   printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
195
196if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
197    printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
198
199mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
200mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
201mysqli_query($link, 'DROP USER pcontest@localhost');
202mysqli_query($link, 'DROP USER pcontest');
203
204mysqli_close($link);
205?>
206--EXPECTF--
207Warning: mysqli_get_links_stats(): no parameters expected in %s on line %d
208NULL
209Before pconnect:array(3) {
210  ["total"]=>
211  int(1)
212  ["active_plinks"]=>
213  int(0)
214  ["cached_plinks"]=>
215  int(0)
216}
217After pconnect:array(3) {
218  ["total"]=>
219  int(2)
220  ["active_plinks"]=>
221  int(1)
222  ["cached_plinks"]=>
223  int(0)
224}
225array(2) {
226  ["id"]=>
227  string(1) "1"
228  ["label"]=>
229  string(1) "a"
230}
231Before second pconnect:array(3) {
232  ["total"]=>
233  int(2)
234  ["active_plinks"]=>
235  int(1)
236  ["cached_plinks"]=>
237  int(0)
238}
239After second pconnect:array(3) {
240  ["total"]=>
241  int(1)
242  ["active_plinks"]=>
243  int(0)
244  ["cached_plinks"]=>
245  int(0)
246}
247array(3) {
248  ["total"]=>
249  int(1)
250  ["active_plinks"]=>
251  int(0)
252  ["cached_plinks"]=>
253  int(0)
254}
255array(2) {
256  ["id"]=>
257  string(1) "1"
258  ["label"]=>
259  string(1) "a"
260}
261[015] Can open more persistent connections than allowed, [0]
262array(3) {
263  ["total"]=>
264  int(3)
265  ["active_plinks"]=>
266  int(2)
267  ["cached_plinks"]=>
268  int(0)
269}
270done!
271