source: test/regfi-threadtest.c@ 245

Last change on this file since 245 was 228, checked in by tim, 14 years ago

added a test case for pyregfi multithreaded use
updated the regfi multithreaded test case
fixed several ctypes interface problems in pyregfi
added locking to pyregfi iterators for thread safety
fixed regfi talloc race conditions with an additional lock

File size: 5.2 KB
Line 
1/*
2 * A program to stress test regfi under multithreaded use.
3 *
4 * Copyright (C) 2005-2011 Timothy D. Morgan
5 * Copyright (C) 2002 Richard Sharpe, rsharpe@richardsharpe.com
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: $
21 */
22
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <strings.h>
28#include <time.h>
29#include <pthread.h>
30#include "regfi.h"
31#include "void_stack.h"
32
33/* Globals, influenced by command line parameters */
34bool print_verbose = false;
35const char* registry_file = NULL;
36
37/* Other globals */
38REGFI_FILE* f;
39
40
41/* XXX: A hack to share some functions with reglookup-recover.c.
42 * Should move these into a proper library at some point.
43 */
44#include "common.c"
45
46
47
48void traverseValueList(REGFI_ITERATOR* iter)
49{
50 const REGFI_VK* value;
51 bool ret;
52
53 for(ret=regfi_iterator_first_value(iter);
54 ret;
55 ret=regfi_iterator_next_value(iter))
56 {
57 value = regfi_iterator_cur_value(iter);
58 printMsgs(iter->f);
59 regfi_free_record(value);
60 }
61}
62
63
64void traverseKeyTree(REGFI_ITERATOR* iter)
65{
66 const REGFI_NK* root = NULL;
67 const REGFI_NK* cur = NULL;
68 const REGFI_NK* sub = NULL;
69 const REGFI_SK* sk;
70 bool print_this = true;
71
72 root = cur = regfi_iterator_cur_key(iter);
73 regfi_iterator_first_subkey(iter);
74 sub = regfi_iterator_cur_subkey(iter);
75 printMsgs(iter->f);
76
77 if(root == NULL)
78 bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: root cannot be NULL.\n");
79
80 do
81 {
82 if(print_this)
83 traverseValueList(iter);
84
85 if(sub == NULL)
86 {
87 if(cur != root)
88 {
89 /* We're done with this sub-tree, going up and hitting other branches. */
90 regfi_free_record(cur);
91 if(!regfi_iterator_up(iter))
92 {
93 printMsgs(iter->f);
94 bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: could not traverse iterator upward.\n");
95 }
96
97 cur = regfi_iterator_cur_key(iter);
98 /* fprintf(stderr, "%s\n", cur->keyname);*/
99 printMsgs(iter->f);
100 if(cur == NULL)
101 bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: unexpected NULL for key.\n");
102 sk = regfi_fetch_sk(iter->f, cur);
103 printMsgs(iter->f);
104 regfi_free_record(sk);
105
106 regfi_iterator_next_subkey(iter);
107 sub = regfi_iterator_cur_subkey(iter);
108 }
109 print_this = false;
110 }
111 else
112 { /* We have unexplored sub-keys.
113 * Let's move down and print this first sub-tree out.
114 */
115 regfi_free_record(cur);
116 if(!regfi_iterator_down(iter))
117 {
118 printMsgs(iter->f);
119 bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: could not traverse iterator downward.\n");
120 }
121
122 cur = regfi_iterator_cur_key(iter);
123 printMsgs(iter->f);
124 regfi_free_record(sub);
125
126 regfi_iterator_first_subkey(iter);
127 sub = regfi_iterator_cur_subkey(iter);
128 printMsgs(iter->f);
129 print_this = true;
130 }
131 printMsgs(iter->f);
132 } while(!((cur == root) && (sub == NULL)));
133 regfi_free_record(root);
134
135 if(print_verbose)
136 fprintf(stderr, "INFO: Finished printing key tree.\n");
137}
138
139
140int num_iterations;
141void* threadLoop(void* file)
142{
143 REGFI_ITERATOR* iter;
144 int i;
145
146 regfi_log_set_mask(REGFI_LOG_INFO|REGFI_LOG_WARN|REGFI_LOG_ERROR);
147
148 iter = regfi_iterator_new((REGFI_FILE*)f);
149 if(iter == NULL)
150 {
151 printMsgs(f);
152 bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Couldn't create registry iterator.\n");
153 }
154
155 for(i=0; i< num_iterations; i++)
156 {
157 traverseKeyTree(iter);
158 regfi_iterator_to_root(iter);
159 }
160
161 regfi_iterator_free(iter);
162
163 return NULL;
164}
165
166
167static void usage(void)
168{
169 fprintf(stderr, "Usage: regfi-threadtest <REGISTRY_FILE>\n");
170 fprintf(stderr, "\n");
171}
172
173
174int main(int argc, char** argv)
175{
176 int fd, tret, i;
177 uint32_t argi, arge, num_threads;
178 pthread_t* threads;
179
180 num_threads = 10;
181 num_iterations = 10;
182
183 /* Process command line arguments */
184 if(argc < 2)
185 {
186 usage();
187 bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: Requires at least one argument.\n");
188 }
189
190 arge = argc-1;
191 for(argi = 1; argi < arge; argi++)
192 {
193 usage();
194 fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
195 bailOut(REGLOOKUP_EXIT_USAGE, "");
196 }
197 registry_file = argv[argi];
198
199 regfi_log_set_mask(REGFI_LOG_INFO|REGFI_LOG_WARN|REGFI_LOG_ERROR);
200
201 fd = openHive(registry_file);
202 if(fd < 0)
203 {
204 fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
205 bailOut(REGLOOKUP_EXIT_NOINPUT, "");
206 }
207
208 f = regfi_alloc(fd, REGFI_ENCODING_ASCII);
209 if(f == NULL)
210 {
211 close(fd);
212 bailOut(REGLOOKUP_EXIT_NOINPUT, "ERROR: Failed to create REGFI_FILE structure.\n");
213 }
214
215 threads = malloc(sizeof(pthread_t)*num_threads);
216 for(i=0; i<num_threads; i++)
217 {
218 tret = pthread_create(threads+i, NULL, threadLoop, (void*) f);
219 }
220
221 for(i=0; i<num_threads; i++)
222 pthread_join(threads[i], NULL);
223
224 free(threads);
225 regfi_free(f);
226 close(fd);
227
228 return 0;
229}
Note: See TracBrowser for help on using the repository browser.