1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of PerconaFT.
6
7
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22 ----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35 ======= */
36
37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39 #pragma once
40
41 #include <portability/toku_atomic.h>
42
43 static toku_mutex_t event_mutex = TOKU_MUTEX_INITIALIZER;
lock_events(void)44 static void lock_events(void) {
45 toku_mutex_lock(&event_mutex);
46 }
unlock_events(void)47 static void unlock_events(void) {
48 toku_mutex_unlock(&event_mutex);
49 }
50 static int event_count, event_count_trigger;
51
52 __attribute__((__unused__))
reset_event_counts(void)53 static void reset_event_counts(void) {
54 lock_events();
55 event_count = event_count_trigger = 0;
56 unlock_events();
57 }
58
59 __attribute__((__unused__))
event_hit(void)60 static void event_hit(void) {
61 }
62
63 __attribute__((__unused__))
event_add_and_fetch(void)64 static int event_add_and_fetch(void) {
65 lock_events();
66 int r = ++event_count;
67 unlock_events();
68 return r;
69 }
70
71 static int do_user_errors = 0;
72
73 __attribute__((__unused__))
loader_poll_callback(void * UU (extra),float UU (progress))74 static int loader_poll_callback(void *UU(extra), float UU(progress)) {
75 int r;
76 if (do_user_errors && event_count_trigger == event_add_and_fetch()) {
77 event_hit();
78 r = 1;
79 } else {
80 r = 0;
81 }
82 return r;
83 }
84
85 static int do_write_errors = 0;
86
87 __attribute__((__unused__))
bad_fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream)88 static size_t bad_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream) {
89 size_t r;
90 if (do_write_errors && event_count_trigger == event_add_and_fetch()) {
91 event_hit();
92 errno = ENOSPC;
93 r = (size_t) -1;
94 } else {
95 r = fwrite(ptr, size, nmemb, stream);
96 if (r!=nmemb) {
97 errno = ferror(stream);
98 }
99 }
100 return r;
101 }
102
103 __attribute__((__unused__))
bad_write(int fd,const void * bp,size_t len)104 static ssize_t bad_write(int fd, const void * bp, size_t len) {
105 ssize_t r;
106 if (do_write_errors && event_count_trigger == event_add_and_fetch()) {
107 event_hit();
108 errno = ENOSPC;
109 r = -1;
110 } else {
111 r = write(fd, bp, len);
112 }
113 return r;
114 }
115
116 __attribute__((__unused__))
bad_pwrite(int fd,const void * bp,size_t len,toku_off_t off)117 static ssize_t bad_pwrite(int fd, const void * bp, size_t len, toku_off_t off) {
118 ssize_t r;
119 if (do_write_errors && event_count_trigger == event_add_and_fetch()) {
120 event_hit();
121 errno = ENOSPC;
122 r = -1;
123 } else {
124 r = pwrite(fd, bp, len, off);
125 }
126 return r;
127 }
128
129 static int do_malloc_errors = 0;
130 static int my_malloc_count = 0, my_big_malloc_count = 0;
131 static int my_realloc_count = 0, my_big_realloc_count = 0;
132 static size_t my_big_malloc_limit = 64*1024;
133
134 __attribute__((__unused__))
reset_my_malloc_counts(void)135 static void reset_my_malloc_counts(void) {
136 my_malloc_count = my_big_malloc_count = 0;
137 my_realloc_count = my_big_realloc_count = 0;
138 }
139
140 __attribute__((__unused__))
my_malloc(size_t n)141 static void *my_malloc(size_t n) {
142 (void) toku_sync_fetch_and_add(&my_malloc_count, 1); // my_malloc_count++;
143 if (n >= my_big_malloc_limit) {
144 (void) toku_sync_fetch_and_add(&my_big_malloc_count, 1); // my_big_malloc_count++;
145 if (do_malloc_errors) {
146 if (event_add_and_fetch() == event_count_trigger) {
147 event_hit();
148 errno = ENOMEM;
149 return NULL;
150 }
151 }
152 }
153 return malloc(n);
154 }
155
156 static int do_realloc_errors = 0;
157
158 __attribute__((__unused__))
my_realloc(void * p,size_t n)159 static void *my_realloc(void *p, size_t n) {
160 (void) toku_sync_fetch_and_add(&my_realloc_count, 1); // my_realloc_count++;
161 if (n >= my_big_malloc_limit) {
162 (void) toku_sync_fetch_and_add(&my_big_realloc_count, 1); // my_big_realloc_count++;
163 if (do_realloc_errors) {
164 if (event_add_and_fetch() == event_count_trigger) {
165 event_hit();
166 errno = ENOMEM;
167 return NULL;
168 }
169 }
170 }
171 return realloc(p, n);
172 }
173