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