source: test/regfi-threadtest.c @ 248

Last change on this file since 248 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.