source: test/regfi-threadtest.c @ 250

Last change on this file since 250 was 250, checked in by tim, 13 years ago

added key caching
readded SK caching
fixed races and deadlocks

File size: 5.6 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
46static bool keysEqual(const REGFI_NK* x, const REGFI_NK* y)
47{
48  return (x != NULL && y != NULL && x->offset == y->offset);
49}
50
51void traverseValueList(REGFI_ITERATOR* iter)
52{
53  const REGFI_VK* value;
54  bool ret;
55
56  for(ret=regfi_iterator_first_value(iter); 
57      ret; 
58      ret=regfi_iterator_next_value(iter))
59  {
60    value = regfi_iterator_cur_value(iter);
61    printMsgs(iter->f);
62    regfi_free_record(iter->f, value);
63  }
64}
65
66
67void traverseKeyTree(REGFI_ITERATOR* iter)
68{
69  const REGFI_NK* root = NULL;
70  const REGFI_NK* cur = NULL;
71  const REGFI_NK* sub = NULL;
72  const REGFI_SK* sk;
73  bool print_this = true;
74
75  root = regfi_iterator_cur_key(iter);
76  regfi_reference_record(iter->f, root);
77  cur = root;
78  regfi_iterator_first_subkey(iter);
79  sub = regfi_iterator_cur_subkey(iter);
80  printMsgs(iter->f);
81
82  if(root == NULL)
83    bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: root cannot be NULL.\n");
84 
85  do
86  {
87    if(print_this)
88      traverseValueList(iter);
89   
90    if(sub == NULL)
91    {
92      if(!keysEqual(cur,root))
93      {
94        /* We're done with this sub-tree, going up and hitting other branches. */
95        regfi_free_record(iter->f, cur);
96        cur = NULL;
97        if(!regfi_iterator_up(iter))
98        {
99          printMsgs(iter->f);
100          bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: could not traverse iterator upward.\n");
101        }
102
103        cur = regfi_iterator_cur_key(iter);
104        /*      fprintf(stderr, "%s\n", cur->keyname);*/
105        printMsgs(iter->f);
106        if(cur == NULL)
107          bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: unexpected NULL for key.\n");
108        sk = regfi_fetch_sk(iter->f, cur);
109        printMsgs(iter->f);
110        regfi_free_record(iter->f, sk);
111
112        regfi_iterator_next_subkey(iter);
113        sub = regfi_iterator_cur_subkey(iter);
114      }
115      print_this = false;
116    }
117    else
118    { /* We have unexplored sub-keys. 
119       * Let's move down and print this first sub-tree out.
120       */
121      regfi_free_record(iter->f, cur);
122      cur = NULL;
123      if(!regfi_iterator_down(iter))
124      {
125        printMsgs(iter->f);
126        bailOut(REGLOOKUP_EXIT_DATAERR, "ERROR: could not traverse iterator downward.\n");
127      }
128
129      cur = regfi_iterator_cur_key(iter);
130      printMsgs(iter->f);
131      regfi_free_record(iter->f, sub);
132
133      regfi_iterator_first_subkey(iter);
134      sub = regfi_iterator_cur_subkey(iter);
135      printMsgs(iter->f);
136      print_this = true;
137    }
138    printMsgs(iter->f);
139  } while(!(keysEqual(cur,root) && (sub == NULL)));
140  if(cur != NULL)
141    regfi_free_record(iter->f, cur);
142  regfi_free_record(iter->f, root);
143
144  if(print_verbose)
145    fprintf(stderr, "INFO: Finished printing key tree.\n");
146}
147
148
149int num_iterations;
150void* threadLoop(void* file)
151{
152  REGFI_ITERATOR* iter;
153  int i;
154
155  regfi_log_set_mask(REGFI_LOG_INFO|REGFI_LOG_WARN|REGFI_LOG_ERROR);
156
157  iter = regfi_iterator_new((REGFI_FILE*)f);
158  if(iter == NULL)
159  {
160    printMsgs(f);
161    bailOut(REGLOOKUP_EXIT_OSERR, "ERROR: Couldn't create registry iterator.\n");
162  }
163
164  for(i=0; i< num_iterations; i++)
165  {
166    traverseKeyTree(iter);
167    regfi_iterator_to_root(iter);
168  }
169
170  regfi_iterator_free(iter);
171
172  return NULL;
173}
174
175
176static void usage(void)
177{
178  fprintf(stderr, "Usage: regfi-threadtest <REGISTRY_FILE>\n");
179  fprintf(stderr, "\n");
180}
181
182
183int main(int argc, char** argv)
184{
185  int fd, tret, i;
186  uint32_t argi, arge, num_threads;
187  pthread_t* threads;
188
189  num_threads = 10;
190  num_iterations = 10;
191
192  /* Process command line arguments */
193  if(argc < 2)
194  {
195    usage();
196    bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: Requires at least one argument.\n");
197  }
198 
199  arge = argc-1;
200  for(argi = 1; argi < arge; argi++)
201  {
202    usage();
203    fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
204    bailOut(REGLOOKUP_EXIT_USAGE, "");
205  }
206  registry_file = argv[argi];
207
208  regfi_log_set_mask(REGFI_LOG_INFO|REGFI_LOG_WARN|REGFI_LOG_ERROR);
209
210  fd = openHive(registry_file);
211  if(fd < 0)
212  {
213    fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
214    bailOut(REGLOOKUP_EXIT_NOINPUT, "");
215  }
216
217  f = regfi_alloc(fd, REGFI_ENCODING_ASCII);
218  if(f == NULL)
219  {
220    close(fd);
221    bailOut(REGLOOKUP_EXIT_NOINPUT, "ERROR: Failed to create REGFI_FILE structure.\n");
222  }
223
224  threads = malloc(sizeof(pthread_t)*num_threads);
225  for(i=0; i<num_threads; i++)
226  {
227    tret = pthread_create(threads+i, NULL, threadLoop, (void*) f);
228  }
229 
230  for(i=0; i<num_threads; i++)
231    pthread_join(threads[i], NULL);
232
233  free(threads);
234  regfi_free(f);
235  close(fd);
236
237  return 0;
238}
Note: See TracBrowser for help on using the repository browser.