source: test/regfi-threadtest.c @ 263

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

simplified string encoding argument passing throughout regfi API

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  fprintf(stderr, "INFO: thread finished\n");
172
173  return NULL;
174}
175
176
177static void usage(void)
178{
179  fprintf(stderr, "Usage: regfi-threadtest <REGISTRY_FILE>\n");
180  fprintf(stderr, "\n");
181}
182
183
184int main(int argc, char** argv)
185{
186  int fd, tret, i;
187  uint32_t argi, arge, num_threads;
188  pthread_t* threads;
189
190  num_threads = 10;
191  num_iterations = 2;
192
193  /* Process command line arguments */
194  if(argc < 2)
195  {
196    usage();
197    bailOut(REGLOOKUP_EXIT_USAGE, "ERROR: Requires at least one argument.\n");
198  }
199 
200  arge = argc-1;
201  for(argi = 1; argi < arge; argi++)
202  {
203    usage();
204    fprintf(stderr, "ERROR: Unrecognized option: %s\n", argv[argi]);
205    bailOut(REGLOOKUP_EXIT_USAGE, "");
206  }
207  registry_file = argv[argi];
208
209  regfi_log_set_mask(REGFI_LOG_INFO|REGFI_LOG_WARN|REGFI_LOG_ERROR);
210
211  fd = openHive(registry_file);
212  if(fd < 0)
213  {
214    fprintf(stderr, "ERROR: Couldn't open registry file: %s\n", registry_file);
215    bailOut(REGLOOKUP_EXIT_NOINPUT, "");
216  }
217
218  f = regfi_alloc(fd, REGFI_ENCODING_ASCII);
219  if(f == NULL)
220  {
221    close(fd);
222    bailOut(REGLOOKUP_EXIT_NOINPUT, "ERROR: Failed to create REGFI_FILE structure.\n");
223  }
224
225  threads = malloc(sizeof(pthread_t)*num_threads);
226  for(i=0; i<num_threads; i++)
227  {
228    tret = pthread_create(threads+i, NULL, threadLoop, (void*) f);
229  }
230 
231  for(i=0; i<num_threads; i++)
232    pthread_join(threads[i], NULL);
233
234  free(threads);
235  regfi_free(f);
236  close(fd);
237
238  return 0;
239}
Note: See TracBrowser for help on using the repository browser.