~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to lib/records/test_RecProcess.i

  • Committer: Bazaar Package Importer
  • Author(s): Arno Toell
  • Date: 2011-01-13 11:49:18 UTC
  • Revision ID: james.westby@ubuntu.com-20110113114918-vu422h8dknrgkj15
Tags: upstream-2.1.5-unstable
ImportĀ upstreamĀ versionĀ 2.1.5-unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 
 
3
  A small test and sample program for librecprocess.a
 
4
 
 
5
  @section license License
 
6
 
 
7
  Licensed to the Apache Software Foundation (ASF) under one
 
8
  or more contributor license agreements.  See the NOTICE file
 
9
  distributed with this work for additional information
 
10
  regarding copyright ownership.  The ASF licenses this file
 
11
  to you under the Apache License, Version 2.0 (the
 
12
  "License"); you may not use this file except in compliance
 
13
  with the License.  You may obtain a copy of the License at
 
14
 
 
15
      http://www.apache.org/licenses/LICENSE-2.0
 
16
 
 
17
  Unless required by applicable law or agreed to in writing, software
 
18
  distributed under the License is distributed on an "AS IS" BASIS,
 
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
20
  See the License for the specific language governing permissions and
 
21
  limitations under the License.
 
22
 */
 
23
 
 
24
#include "ink_hrtime.h"
 
25
#include "P_RecUtils.h"
 
26
#include "test_RecordsConfig.h"
 
27
 
 
28
Diags *diags = NULL;
 
29
 
 
30
void RecDumpRecordsHt(RecT rec_type);
 
31
 
 
32
void
 
33
syslog_thr_init()
 
34
{
 
35
  openlog("test_I_RecProcess", LOG_PID | LOG_NDELAY | LOG_NOWAIT, LOG_USER);
 
36
}
 
37
 
 
38
//-------------------------------------------------------------------------
 
39
// Test01: Parse Tests
 
40
//
 
41
// The following test just verifies that we can parse the
 
42
// 'records.config' file format correctly (e.g can we handle weird
 
43
// spacing, malformed lines, etc).  The test also verifies some of the
 
44
// basic RecGetRecord functionality.
 
45
//
 
46
// Run this test with the 'test_records.config' config file.  Note
 
47
// that the configs used by this test are registered in the
 
48
// 'test_RecordsConfig.cc' file.
 
49
//-------------------------------------------------------------------------
 
50
 
 
51
#define PARSE_TEST_UNAVAILABLE(name, failures) \
 
52
  do { \
 
53
    RecString rec_string = 0; \
 
54
    if (RecGetRecordString_Xmalloc("proxy.config.parse_"name, &rec_string) != REC_ERR_FAIL) { \
 
55
      if (rec_string) xfree(rec_string); \
 
56
      printf("  parse_"name": FAIL\n"); \
 
57
      failures++; \
 
58
    } else { \
 
59
      printf("  parse_"name": PASS\n"); \
 
60
    } \
 
61
  } while (0);
 
62
 
 
63
#define PARSE_TEST_COMPARE(name, value, failures) \
 
64
  do { \
 
65
    RecString rec_string = 0; \
 
66
    if (RecGetRecordString_Xmalloc("proxy.config.parse_"name, &rec_string) == REC_ERR_OKAY) { \
 
67
      if (strcmp(rec_string, value) == 0) { \
 
68
        printf("  parse_"name": PASS\n"); \
 
69
      } else { \
 
70
        printf("  parse_"name": FAIL\n"); \
 
71
        failures++; \
 
72
      } \
 
73
      xfree(rec_string); \
 
74
    } else { \
 
75
      printf("  parse_"name": FAIL\n"); \
 
76
      failures++; \
 
77
    } \
 
78
  } while (0);
 
79
 
 
80
void
 
81
Test01()
 
82
{
 
83
  printf("[Test01: Parse Tests]\n");
 
84
  int failures = 0;
 
85
 
 
86
  // test 1 and 1b
 
87
  PARSE_TEST_UNAVAILABLE("test_1a", failures);
 
88
  PARSE_TEST_UNAVAILABLE("test_1b", failures);
 
89
 
 
90
  // test 2, 2b, 3, 3b, 4, 4b
 
91
  PARSE_TEST_COMPARE("test_2a", "X", failures);
 
92
  PARSE_TEST_COMPARE("test_2b", "X", failures);
 
93
  PARSE_TEST_COMPARE("test_3b", "XXX", failures);
 
94
  PARSE_TEST_COMPARE("test_3b", "XXX", failures);
 
95
  PARSE_TEST_COMPARE("test_4a", "XXX XXX XXX", failures);
 
96
  PARSE_TEST_COMPARE("test_4b", "XXX XXX XXX", failures);
 
97
 
 
98
  if (failures == 0) {
 
99
    printf("  SUMMARY: PASS\n");
 
100
  } else {
 
101
    printf("  SUMMARY: FAIL\n");
 
102
  }
 
103
  return;
 
104
}
 
105
 
 
106
//-------------------------------------------------------------------------
 
107
// Test02: Config Tests
 
108
//
 
109
// The following test stresses some additional config features
 
110
// (e.g. registration of config update callbacks, config linking, and
 
111
// config setting).  As with Test01, config registration must be done
 
112
// in 'test_RecordsConfig.cc'.
 
113
//-------------------------------------------------------------------------
 
114
 
 
115
bool g_config_update_result = false;
 
116
 
 
117
RecInt g_link_test_1 = 0;
 
118
RecFloat g_link_test_2 = 0.0f;
 
119
RecCounter g_link_test_3 = 0;
 
120
 
 
121
int
 
122
cb_test_1(const char *name, RecDataT data_type, RecData data, void *cookie)
 
123
{
 
124
  NOWARN_UNUSED(data_type);
 
125
  if ((cookie == (void *) 0x12345678) && (strcmp(data.rec_string, "cb_test_1__changed") == 0)) {
 
126
    printf("    - cb_test_1 (name: %s, data: %s, cookie: 0x%x\n", name, data.rec_string, cookie);
 
127
    g_config_update_result = true;
 
128
  } else {
 
129
    g_config_update_result = false;
 
130
  }
 
131
  return REC_ERR_OKAY;
 
132
}
 
133
 
 
134
int
 
135
cb_test_2(const char *name, RecDataT data_type, RecData data, void *cookie)
 
136
{
 
137
  NOWARN_UNUSED(name);
 
138
  NOWARN_UNUSED(data_type);
 
139
  NOWARN_UNUSED(data);
 
140
  NOWARN_UNUSED(cookie);
 
141
  g_config_update_result = false;
 
142
  return REC_ERR_FAIL;
 
143
}
 
144
 
 
145
void
 
146
Test02()
 
147
{
 
148
  printf("[Test02: Config Tests]\n");
 
149
  int failures = 0;
 
150
 
 
151
  printf("  [RecRegisterConfigUpdateCb]\n");
 
152
 
 
153
  // Initialize variables
 
154
  RecSetRecordString("proxy.config.cb_test_1", "cb_test_1__original");
 
155
  RecSetRecordString("proxy.config.cb_test_2", "cb_test_2__original");
 
156
  printf("    - sleep(2*REC_CONFIG_UPDATE_INTERVAL_SEC)\n");
 
157
  ink_sleep(2 * REC_CONFIG_UPDATE_INTERVAL_SEC);
 
158
 
 
159
  // Register config update callbacks
 
160
  RecRegisterConfigUpdateCb("proxy.config.cb_test_1", cb_test_1, (void *) 0x12345678);
 
161
  RecRegisterConfigUpdateCb("proxy.config.cb_test_2", cb_test_2, (void *) 0x87654321);
 
162
 
 
163
  // Change proxy.config.cb_test_1
 
164
  RecSetRecordString("proxy.config.cb_test_1", "cb_test_1__changed");
 
165
  printf("    - sleep(2*REC_CONFIG_UPDATE_INTERVAL_SEC)\n");
 
166
  ink_sleep(2 * REC_CONFIG_UPDATE_INTERVAL_SEC);
 
167
 
 
168
  // Check globals to make sure the right thing happened
 
169
  if (g_config_update_result == true) {
 
170
    printf("    SUMMARY: PASS\n");
 
171
  } else {
 
172
    printf("    SUMMARY: FAIL\n");
 
173
  }
 
174
 
 
175
  printf("  [RecLinkConfigXXX]\n");
 
176
 
 
177
  // Set configs
 
178
  RecSetRecordInt("proxy.config.link_test_1", 1);
 
179
  RecSetRecordFloat("proxy.config.link_test_2", 100.0f);
 
180
  RecSetRecordCounter("proxy.config.link_test_3", 5);
 
181
  printf("    - sleep(2*REC_CONFIG_UPDATE_INTERVAL_SEC)\n");
 
182
  ink_sleep(2 * REC_CONFIG_UPDATE_INTERVAL_SEC);
 
183
 
 
184
  // Link configs
 
185
  RecLinkConfigInt("proxy.config.link_test_1", &g_link_test_1);
 
186
  RecLinkConfigFloat("proxy.config.link_test_2", &g_link_test_2);
 
187
  RecLinkConfigCounter("proxy.config.link_test_3", &g_link_test_3);
 
188
 
 
189
  // Initial check to make sure link worked
 
190
  printf("    - g_link_test_1 = %d:%d, expect: 1\n", g_link_test_1);
 
191
  printf("    - g_link_test_2 = %f, expect: %f\n", g_link_test_2, 100.0f);
 
192
  printf("    - g_link_test_3 = %d:%d, expect: 5\n", g_link_test_3);
 
193
  if (g_link_test_1 == 1 && g_link_test_2 == 100.0f && g_link_test_3 == 5) {
 
194
    printf("    SUMMARY: PASS\n");
 
195
  } else {
 
196
    printf("    SUMMARY: FAIL\n");
 
197
  }
 
198
 
 
199
  printf("  [RecGetRecordXXX]\n");
 
200
  failures = 0;
 
201
  RecString rec_string = 0;
 
202
  const int buf_len = 1024;
 
203
  char buf[buf_len];
 
204
 
 
205
  RecGetRecordString_Xmalloc("proxy.config.cb_test_2", &rec_string);
 
206
  if (!rec_string || (rec_string && strcmp(rec_string, "cb_test_2__original")) != 0) {
 
207
    printf("    RecGetRecordString_Xmalloc: FAIL (expected: 'cb_test_2__original', got: '%s')\n",
 
208
           rec_string ? rec_string : "<nothing>");
 
209
  } else {
 
210
    printf("    RecGetRecordString_Xmalloc: PASS (%s)\n", rec_string);
 
211
  }
 
212
 
 
213
  RecGetRecordString("proxy.config.cb_test_2", buf, buf_len);
 
214
  if (strcmp(buf, "cb_test_2__original") != 0) {
 
215
    printf("    RecGetRecordString:         FAIL (expected: 'cb_test_2__original', got: '%s')\n", buf);
 
216
  } else {
 
217
    printf("    RecGetRecordString:         PASS (%s)\n", buf);
 
218
  }
 
219
 
 
220
  // Testing with RecGetRecordInt, RecGetRecordFloat and RecGetRecordCounter
 
221
  RecInt rec_int = 0;
 
222
  RecGetRecordInt("proxy.config.link_test_1", &rec_int);
 
223
  if (rec_int != 1) {
 
224
    printf("    RecGetRecordInt:            FAIL (expected: 1, got %d:%d)\n", rec_int);
 
225
  } else {
 
226
    printf("    RecGetRecordInt:            PASS (%d:%d)\n", rec_int);
 
227
  }
 
228
 
 
229
  RecFloat rec_float = 0;
 
230
  RecGetRecordFloat("proxy.config.link_test_2", &rec_float);
 
231
  if (rec_float != 100.0f) {
 
232
    printf("    RecGetRecordFloat:          FAIL (expected: %f, got %f)\n", 100.0f, rec_float);
 
233
  } else {
 
234
    printf("    RecGetRecordFloat:          PASS (%f)\n", rec_float);
 
235
  }
 
236
 
 
237
  RecCounter rec_counter = 0;
 
238
  RecGetRecordCounter("proxy.config.link_test_3", &rec_counter);
 
239
  if (rec_counter != 5) {
 
240
    printf("    RecGetRecordCounter:        FAIL (expected: 5, got %d:%d)\n", rec_counter);
 
241
  } else {
 
242
    printf("    RecGetRecordCounter:        PASS (%d:%d)\n", rec_counter);
 
243
  }
 
244
 
 
245
  // Testing RecLinkConfigXXX, after calling RecLinkConfigXXX above, those
 
246
  // variable will automatically be atomically updated when record changes in 
 
247
  // librecords.
 
248
  printf("  [RecLinkConfigXXX]\n");
 
249
 
 
250
  // Set the records
 
251
  printf("    - RecSetRecordXXX\n");
 
252
  RecSetRecordString("proxy.config.cb_test_1", "cb_test_1_changed");
 
253
  RecSetRecordInt("proxy.config.link_test_1", 2);
 
254
  RecSetRecordFloat("proxy.config.link_test_2", 200.0f);
 
255
  RecSetRecordCounter("proxy.config.link_test_3", 6);
 
256
  printf("    - sleep(2*REC_CONFIG_UPDATE_INTERVAL_SEC)\n");
 
257
  ink_sleep(2 * REC_CONFIG_UPDATE_INTERVAL_SEC);
 
258
 
 
259
  printf("    - g_link_test_1 = %d:%d, expect: 2\n", g_link_test_1);
 
260
  printf("    - g_link_test_2 = %f, expect: %f\n", g_link_test_2, 200.0f);
 
261
  printf("    - g_link_test_3 = %d:%d, expect: 6\n", g_link_test_3);
 
262
  if (g_link_test_1 == 2 && g_link_test_2 == 200.0f && g_link_test_3 == 6) {
 
263
    printf("    SUMMARY: PASS\n");
 
264
  } else {
 
265
    printf("    SUMMARY: FAIL\n");
 
266
  }
 
267
 
 
268
  RecSetRecordInt("proxy.config.link_test_1", 1);
 
269
  RecSetRecordFloat("proxy.config.link_test_2", 100.0f);
 
270
  RecSetRecordCounter("proxy.config.link_test_3", 5);
 
271
  printf("    - sleep(2*REC_CONFIG_UPDATE_INTERVAL_SEC)\n");
 
272
  ink_sleep(2 * REC_CONFIG_UPDATE_INTERVAL_SEC);
 
273
 
 
274
}
 
275
 
 
276
//-------------------------------------------------------------------------
 
277
// Test03: RawStat Tests
 
278
//
 
279
// The following test illustrates how one might use the RawStat
 
280
// interface to librecprocess.a.  It also illustrates a custom RawStat
 
281
// sync function, 'raw_stat_sync_ticks_per_sec' that computes
 
282
// operations per second (used by AIO module).
 
283
//-------------------------------------------------------------------------
 
284
 
 
285
enum my_stat_enum
 
286
{
 
287
  MY_STAT_A,
 
288
  MY_STAT_B,
 
289
  MY_STAT_C,
 
290
  MY_STAT_D,
 
291
  MY_STAT_E,
 
292
  MY_STAT_F,
 
293
  MY_STAT_G,
 
294
  MY_STAT_COUNT
 
295
};
 
296
 
 
297
static RecRawStatBlock *g_rsb = NULL;
 
298
static int g_count = 0;
 
299
 
 
300
static int g_ticks = 0;
 
301
static int g_time = 0;
 
302
 
 
303
int
 
304
raw_stat_sync_ticks_per_sec(const char *name, RecDataT data_type, RecData * data, RecRawStatBlock * rsb, int id)
 
305
{
 
306
  NOWARN_UNUSED(name);
 
307
  NOWARN_UNUSED(data_type);
 
308
 
 
309
  ink64 ticks_old, time_old;
 
310
  ink64 ticks_new, time_new;
 
311
 
 
312
  RecRawStat *rrs = RecGetGlobalRawStatPtr(rsb, id);
 
313
  ink64 *rrs_sum = RecGetGlobalRawStatSumPtr(rsb, id);
 
314
  ink64 *rrs_count = RecGetGlobalRawStatCountPtr(rsb, id);
 
315
 
 
316
  RecGetGlobalRawStatSum(rsb, id, &ticks_old);
 
317
  RecGetGlobalRawStatCount(rsb, id, &time_old);
 
318
 
 
319
  if ((rrs->sum != ticks_old) && (*rrs_sum != ticks_old)) {
 
320
    printf("ERROR: (rrs->sum != ticks_old) && (*rrs_sum != ticks_old)\n");
 
321
  }
 
322
  /*else {
 
323
     printf("OKAY: GlobalRawStatSum == RecRawStat->sum == && GlobalRawStatSum == GlobalRawStatSumPtr, which is %d:%d\n", ticks_old);
 
324
     } */
 
325
  if ((rrs->count != time_old) && (*rrs_count != time_old)) {
 
326
    printf("ERROR: (rrs->count != time_old) && (*rrs_sum != ticks_old)\n");
 
327
  }
 
328
  /*else {
 
329
     printf("OKAY: GlobalRawStatCount == RecRawStat->count && GlobalRawStatCount == GlobalRawStatCountPtr, which is %d:%d\n", time_old);
 
330
     } */
 
331
  ticks_new = g_ticks;
 
332
  time_new = g_time;
 
333
 
 
334
  data->rec_float = (float) (ticks_new - ticks_old) / (float) (time_new - time_old);
 
335
 
 
336
  RecSetGlobalRawStatSum(rsb, id, ticks_new);
 
337
  RecSetGlobalRawStatCount(rsb, id, time_new);
 
338
 
 
339
  return REC_ERR_OKAY;
 
340
 
 
341
}
 
342
 
 
343
struct RawStatCont:public Continuation
 
344
{
 
345
  RawStatCont(ProxyMutex * m):Continuation(m)
 
346
  {
 
347
    SET_HANDLER(&RawStatCont::dummy_function);
 
348
  }
 
349
  int dummy_function(int event, Event * e)
 
350
  {
 
351
    NOWARN_UNUSED(event);
 
352
    NOWARN_UNUSED(e);
 
353
    printf("------------Raw Stat dump-------------\n");
 
354
    ink64 hr_start, hr_finish;
 
355
    // comments out here. Why stat_a is int?
 
356
    RecInt stat_b, stat_c, stat_f, stat_g;
 
357
    RecFloat stat_a, stat_d, stat_e;
 
358
    // comments out here
 
359
 
 
360
    hr_start = ink_get_hrtime();
 
361
 
 
362
    // test_raw_stat_a should have around 16000 in it (avg of rand())
 
363
    RecIncrRawStat(g_rsb, mutex->thread_holding, (int) MY_STAT_A, rand());
 
364
 
 
365
    // test_raw_stat_b should have g_count plustorial in it
 
366
    RecIncrRawStatSum(g_rsb, mutex->thread_holding, (int) MY_STAT_B, g_count);
 
367
 
 
368
    // test_raw_stat_c should have g_count plustorial in it
 
369
    //RecSetRawStatCount(g_rsb, (int) MY_STAT_C, g_count);
 
370
    RecIncrRawStatCount(g_rsb, mutex->thread_holding, (int) MY_STAT_C, g_count);
 
371
 
 
372
    // test_raw_stat_f should have g_count in it
 
373
    // I have switched this with test_raw_stat_c
 
374
    RecSetRawStatCount(g_rsb, (int) MY_STAT_F, g_count);
 
375
 
 
376
    // test_raw_stat_g should have g_count in it
 
377
    RecSetRawStatSum(g_rsb, (int) MY_STAT_G, g_count);
 
378
 
 
379
    // test_raw_stat_d should have 4 it (e.g. we're run 4 times a second)
 
380
    ink_atomic_increment(&g_ticks, 1);
 
381
    g_time = time(0);
 
382
 
 
383
    // sleep for a bit to take some time
 
384
    struct timespec rgtp;
 
385
    rgtp.tv_sec = 0;
 
386
    rgtp.tv_nsec = 10000;
 
387
    nanosleep(&rgtp, NULL);
 
388
 
 
389
    // FIXME: Read values and compare against expected values rather
 
390
    // than just printing out
 
391
 
 
392
    // comments out here
 
393
    RecGetRecordFloat("proxy.process.test_raw_stat_a", &stat_a);
 
394
    RecGetRecordInt("proxy.process.test_raw_stat_b", &stat_b);
 
395
    RecGetRecordInt("proxy.process.test_raw_stat_c", &stat_c);
 
396
    RecGetRecordFloat("proxy.process.test_raw_stat_d", &stat_d);
 
397
    RecGetRecordFloat("proxy.process.test_raw_stat_e", &stat_e);
 
398
    RecGetRecordInt("proxy.process.test_raw_stat_f", &stat_f);
 
399
    RecGetRecordInt("proxy.process.test_raw_stat_g", &stat_g);
 
400
 
 
401
    /*
 
402
       printf("-> g_count: %d, thr: 0x%x, stat_a: %d%d, stat_b: %d:%d, stat_c: %d:%d, stat_d: %f\n",
 
403
       g_count, mutex->thread_holding, stat_a, stat_b, stat_c, stat_d);
 
404
 
 
405
       printf("-> g_link_test_1: %d:%d, g_link_test_2: %f\n",
 
406
       g_link_test_1, g_link_test_2);
 
407
     */
 
408
 
 
409
    // Compare read value stat_a and expected value test_raw_stat_a
 
410
    RecRawStat test_raw_stat_a;
 
411
    RecFloat avg = 0.0f;
 
412
    test_raw_stat_a.sum = REC_ATOMIC_READ64(&(g_rsb->global[MY_STAT_A]->sum));
 
413
    test_raw_stat_a.count = REC_ATOMIC_READ64(&(g_rsb->global[MY_STAT_A]->count));
 
414
    if (test_raw_stat_a.count != 0)
 
415
      avg = (float) ((double) test_raw_stat_a.sum / (double) test_raw_stat_a.count);
 
416
 
 
417
    if (stat_a != avg) {
 
418
      printf("ERROR: stat_a: %f, expect stat_a: %f\n", stat_a, avg);
 
419
    } else {
 
420
      printf("OKAY: stat_a: %f, expect stat_a: %f\n", stat_a, avg);
 
421
    }
 
422
 
 
423
    // Compare read value stat_b and expected value test_raw_stat_b
 
424
    RecRawStat test_raw_stat_b;
 
425
    test_raw_stat_b.sum = REC_ATOMIC_READ64(&(g_rsb->global[MY_STAT_B]->sum));
 
426
    if (stat_b != test_raw_stat_b.sum) {
 
427
      printf("ERROR: After RecIncrRawStatSum, stat_b: %d:%d, expect stat_b: %d:%d\n", stat_b, test_raw_stat_b.sum);
 
428
    } else {
 
429
      printf("OKAY: After RecIncrRawStatSum, stat_b: %d:%d, expect stat_b: %d:%d\n", stat_b, test_raw_stat_b.sum);
 
430
    }
 
431
 
 
432
    // Compare read value stat_c and expected value test_raw_stat_c
 
433
    RecRawStat test_raw_stat_c;
 
434
    test_raw_stat_c.count = REC_ATOMIC_READ64(&(g_rsb->global[MY_STAT_C]->count));
 
435
    if (stat_c != test_raw_stat_c.count) {
 
436
      printf("ERROR: After RecIncrRawStatCount, stat_c: %d:%d, expect stat_c: %d:%d\n", stat_c, test_raw_stat_c.count);
 
437
    } else {
 
438
      printf("OKAY: After RecIncrRawStatCount, stat_c: %d:%d, expect stat_c: %d:%d\n", stat_c, test_raw_stat_c.count);
 
439
    }
 
440
 
 
441
    // Compare read value stat_d and expected value test_raw_stat_d
 
442
    ink64 ticks_old, time_old;
 
443
    RecGetGlobalRawStatSum(g_rsb, MY_STAT_D, &ticks_old);
 
444
    RecGetGlobalRawStatCount(g_rsb, MY_STAT_D, &time_old);
 
445
    RecFloat data = (float) (g_ticks - ticks_old) / (float) (g_time - time_old);
 
446
    if (stat_d != 4.0f) {
 
447
      printf("ERROR: stat_d: %f, expect stat_d: %f or I got data: %f\n", stat_d, 4.0f, data);
 
448
    } else {
 
449
      printf("OKAY: stat_d: %f, expect stat_d: %f or I got data: %f\n", stat_d, 4.0f, data);
 
450
    }
 
451
 
 
452
    // Compare read value stat_e and expected value test_raw_stat_e
 
453
    RecRawStat test_raw_stat_e;
 
454
    RecFloat r;
 
455
    test_raw_stat_e.sum = REC_ATOMIC_READ64(&(g_rsb->global[MY_STAT_E]->sum));
 
456
    test_raw_stat_e.count = REC_ATOMIC_READ64(&(g_rsb->global[MY_STAT_E]->count));
 
457
    if (test_raw_stat_e.count == 0) {
 
458
      r = 0.0f;
 
459
    } else {
 
460
      r = (float) ((double) test_raw_stat_e.sum / (double) test_raw_stat_e.count);
 
461
      r = r / (float) (HRTIME_SECOND);
 
462
    }
 
463
    if (stat_e != r) {
 
464
      printf("ERROR: stat_e: %f, expect stat_e from avg: %f\n", stat_e, r);
 
465
    } else {
 
466
      printf("OKAY: stat_e: %f, expect stat_e from avg: %f\n", stat_e, r);
 
467
    }
 
468
 
 
469
    // Compare read value stat_f and expected value test_raw_stat_f
 
470
    // Since RecSet only set g_rsb->global[MY_STAT_F]->count to be g_count value. 
 
471
    // It will not set data.rec_int for stat_f until the RecExecRawStatSyncCbs 
 
472
    // is called. RecExecRawStatSyncCbs callback RecRawStatSyncCount which set
 
473
    // data.rec_int to be g_rsb->global[MY_STAT_F]->count. The schedule for
 
474
    // RecExecRawStatSyncCbs is REC_RAW_STAT_SYNC_INTERVAL_SEC = 3 secs.
 
475
    // The normal for this dummy_function is 1 sec. There is no way we can
 
476
    // get the right value for this. Let ask Eric for this :)
 
477
    // I have increase the ink_sleep time (about 3 secs) between RecSet and RecGet 
 
478
    // for stat_c hoping that we got the RecExecRawStatSyncCbs at the middle of them
 
479
    // so we can get the right value for stat_c. However, this will screw up 
 
480
    // stat_d badly as we get NaN for stat_d.
 
481
    RecRawStat test_raw_stat_f;
 
482
    test_raw_stat_f.count = REC_ATOMIC_READ64(&(g_rsb->global[MY_STAT_F]->count));
 
483
    RecInt check_stat_f;
 
484
    RecGetRawStatCount(g_rsb, (int) MY_STAT_F, &check_stat_f);
 
485
    if (stat_f != test_raw_stat_f.count || stat_f != check_stat_f) {
 
486
      printf("ERROR: After RecSetRawStatCount, stat_f: %d:%d, stat_f by REC_ATOMIC_READ64: %d:%d\n", stat_f,
 
487
             test_raw_stat_f.count);
 
488
      printf("       stat_f by RecGetRawStatCount: %d:%d\n", check_stat_f);
 
489
    } else {
 
490
      printf("OKAY: After RecSetRawStatCount, stat_f: %d:%d, stat_f by REC_ATOMIC_READ64: %d:%d\n", stat_f,
 
491
             test_raw_stat_f.count);
 
492
      printf("      stat_f by RecGetRawStatCount: %d:%d\n", check_stat_f);
 
493
    }
 
494
 
 
495
    // Compare read value stat_g and expeced value test_raw_stat_g
 
496
    RecRawStat test_raw_stat_g;
 
497
    test_raw_stat_g.sum = REC_ATOMIC_READ64(&(g_rsb->global[MY_STAT_G]->sum));
 
498
    RecInt check_stat_g;
 
499
    RecGetRawStatSum(g_rsb, (int) MY_STAT_G, &check_stat_g);
 
500
    if (stat_g != test_raw_stat_g.count || stat_g != check_stat_g) {
 
501
      printf("ERROR: After RecSetRawStatSum, stat_g: %d:%d, stat_g by REC_ATOMIC_READ64: %d:%d\n", stat_g,
 
502
             test_raw_stat_g.sum);
 
503
      printf("       stat_g by RecGetRawStatSum: %d:%d\n", check_stat_g);
 
504
    } else {
 
505
      printf("OKAY: After RecSetRawStatSum, stat_g: %d:%d, stat_g by REC_ATOMIC_READ64: %d:%d\n", stat_g,
 
506
             test_raw_stat_g.sum);
 
507
      printf("      stat_g by RecGetRawStatSum: %d:%d\n", check_stat_g);
 
508
    }
 
509
    ink_atomic_increment(&g_count, 1);
 
510
 
 
511
    // test_raw_stat_e should have the time it takes to run this function
 
512
    hr_finish = ink_get_hrtime();
 
513
    RecIncrRawStat(g_rsb, mutex->thread_holding, (int) MY_STAT_E, hr_finish - hr_start);
 
514
 
 
515
    return 0;
 
516
  }
 
517
};
 
518
 
 
519
void
 
520
Test03()
 
521
{
 
522
  printf("[Test03: RawStat Test]\n");
 
523
 
 
524
  // Register raw statistics 
 
525
  g_rsb = RecAllocateRawStatBlock((int) MY_STAT_COUNT);
 
526
 
 
527
  RecRegisterRawStat(g_rsb, RECT_PROCESS, "proxy.process.test_raw_stat_a",
 
528
                     RECD_FLOAT, RECP_NULL, (int) MY_STAT_A, RecRawStatSyncAvg);
 
529
 
 
530
  RecRegisterRawStat(g_rsb, RECT_PROCESS, "proxy.process.test_raw_stat_b",
 
531
                     RECD_INT, RECP_PERSISTENT, (int) MY_STAT_B, RecRawStatSyncSum);
 
532
 
 
533
  RecRegisterRawStat(g_rsb, RECT_PROCESS, "proxy.process.test_raw_stat_c",
 
534
                     RECD_INT, RECP_NULL, (int) MY_STAT_C, RecRawStatSyncCount);
 
535
 
 
536
  RecRegisterRawStat(g_rsb, RECT_PROCESS, "proxy.process.test_raw_stat_d",
 
537
                     RECD_FLOAT, RECP_NULL, (int) MY_STAT_D, raw_stat_sync_ticks_per_sec);
 
538
 
 
539
  RecRegisterRawStat(g_rsb, RECT_PROCESS, "proxy.process.test_raw_stat_e",
 
540
                     RECD_FLOAT, RECP_NULL, (int) MY_STAT_E, RecRawStatSyncHrTimeAvg);
 
541
  RecRegisterRawStat(g_rsb, RECT_PROCESS, "proxy.process.test_raw_stat_f",
 
542
                     RECD_INT, RECP_NULL, (int) MY_STAT_F, RecRawStatSyncCount);
 
543
  // If forget to Register this RawStat, we will have SEGV when checking 
 
544
  // g_rsb->global[MY_STAT_G]
 
545
  RecRegisterRawStat(g_rsb, RECT_PROCESS, "proxy.process.test_raw_stat_g",
 
546
                     RECD_INT, RECP_NULL, (int) MY_STAT_G, RecRawStatSyncSum);
 
547
 
 
548
  // Schedule a bunch of continuations that will use the stats registered above
 
549
  RawStatCont *sc = new RawStatCont(new_ProxyMutex());
 
550
  eventProcessor.schedule_every(sc, HRTIME_SECONDS(1), ET_CALL, EVENT_INTERVAL, NULL);
 
551
  eventProcessor.schedule_every(sc, HRTIME_SECONDS(1), ET_CALL, EVENT_INTERVAL, NULL);
 
552
  eventProcessor.schedule_every(sc, HRTIME_SECONDS(1), ET_CALL, EVENT_INTERVAL, NULL);
 
553
  eventProcessor.schedule_every(sc, HRTIME_SECONDS(1), ET_CALL, EVENT_INTERVAL, NULL);
 
554
 
 
555
}
 
556
 
 
557
//-------------------------------------------------------------------------
 
558
// DumpRecordHtCont
 
559
//-------------------------------------------------------------------------
 
560
 
 
561
struct DumpRecordsHtCont:public Continuation
 
562
{
 
563
  DumpRecordsHtCont(ProxyMutex * m):Continuation(m)
 
564
  {
 
565
    SET_HANDLER(&DumpRecordsHtCont::dummy_function);
 
566
  }
 
567
  int dummy_function(int event, Event * e)
 
568
  {
 
569
    NOWARN_UNUSED(event);
 
570
    NOWARN_UNUSED(e);
 
571
    RecDumpRecordsHt(RECT_NULL);
 
572
    return 0;
 
573
  }
 
574
};
 
575
 
 
576
//-------------------------------------------------------------------------
 
577
// TreeTest01: 
 
578
//
 
579
//-------------------------------------------------------------------------
 
580
 
 
581
void
 
582
TreeTest01()
 
583
{
 
584
  char **var_buf = NULL;
 
585
  int buf_len = 0;
 
586
  RecGetRecordList("proxy.config", &var_buf, &buf_len);
 
587
  for (int i = 0; i < buf_len; i++) {
 
588
    ink_debug_assert(var_buf[i]);
 
589
    diags->print(NULL, DL_Note, NULL, NULL, "\tRecTree node: (proxy.config.*) %s", var_buf[i]);
 
590
  }
 
591
  delete[]var_buf;
 
592
  printf("\n");
 
593
  if (buf_len == 12) {
 
594
    diags->print(NULL, DL_Note, NULL, NULL, "\tRecTree Test -- PASS\n");
 
595
  } else {
 
596
    diags->print(NULL, DL_Note, NULL, NULL, "\tRecTree Test -- FAIL\n");
 
597
  }
 
598
  printf("\n");
 
599
}
 
600
 
 
601
 
 
602
//-------------------------------------------------------------------------
 
603
// TreeTest02: 
 
604
//
 
605
// This should only run after Test03.
 
606
// Determine whether proxy.process.* variable are referred by the RecTree
 
607
// properly.
 
608
//-------------------------------------------------------------------------
 
609
 
 
610
void
 
611
TreeTest02()
 
612
{
 
613
  char **var_buf = NULL;
 
614
  int buf_len = 0;
 
615
  RecGetRecordList("proxy.process", &var_buf, &buf_len);
 
616
  for (int i = 0; i < buf_len; i++) {
 
617
    ink_debug_assert(var_buf[i]);
 
618
    diags->print(NULL, DL_Note, NULL, NULL, "\tRecTree (proxy.process.*) node: %s", var_buf[i]);
 
619
  }
 
620
  delete[]var_buf;
 
621
  printf("\n");
 
622
  if (buf_len == 7) {
 
623
    diags->print(NULL, DL_Note, NULL, NULL, "\tRecTree Test -- PASS\n");
 
624
  } else {
 
625
    diags->print(NULL, DL_Note, NULL, NULL, "\tRecTree Test -- FAIL\n");
 
626
  }
 
627
  printf("\n");
 
628
}
 
629
 
 
630
//-------------------------------------------------------------------------
 
631
// main
 
632
//-------------------------------------------------------------------------
 
633
 
 
634
int
 
635
main(int argc, char **argv)
 
636
{
 
637
 
 
638
  RecModeT mode_type = RECM_STAND_ALONE;
 
639
  if ((argc == 2) && (strcmp(argv[1], "-M") == 0)) {
 
640
    mode_type = RECM_CLIENT;
 
641
  }
 
642
  // Start diags logging
 
643
  FILE *log_fp;
 
644
  if ((log_fp = fopen("recprocess.log", "a+")) != NULL) {
 
645
    int status = setvbuf(log_fp, NULL, _IOLBF, 512);
 
646
    if (status != 0) {
 
647
      fclose(log_fp);
 
648
      log_fp = NULL;
 
649
    }
 
650
  }
 
651
  diags = NEW(new Diags("rec", NULL, log_fp));
 
652
  diags->activate_taglist(diags->base_debug_tags, DiagsTagType_Debug);
 
653
  diags->print(NULL, DL_Note, NULL, NULL, "Starting '%s'", argv[0]);
 
654
 
 
655
  // System initialization.  Note that a pointer to the diags object
 
656
  // is passed into librecprocess.a.  If manager isn't running, we
 
657
  // need to register our own configs
 
658
  RecProcessInit(mode_type, diags);
 
659
  RecProcessInitMessage(mode_type);
 
660
  if (mode_type == RECM_STAND_ALONE) {
 
661
    RecordsConfigRegister();
 
662
  }
 
663
  ink_event_system_init(EVENT_SYSTEM_MODULE_VERSION);
 
664
  eventProcessor.start(4);
 
665
  RecProcessStart();
 
666
 
 
667
  RecSignalManager(1, "This is a signal, signaled by RecSignalManager");
 
668
 
 
669
  // See if we're sync'd okay
 
670
  RecDumpRecordsHt(RECT_NULL);
 
671
 
 
672
 
 
673
  // Run tests
 
674
  TreeTest01();
 
675
  Test01();
 
676
  Test02();
 
677
  Test03();
 
678
  TreeTest02();
 
679
 
 
680
 
 
681
  // Schedule dump continuation so that we can see what's going on
 
682
  DumpRecordsHtCont *drhc = new DumpRecordsHtCont(new_ProxyMutex());
 
683
  eventProcessor.schedule_every(drhc, HRTIME_SECONDS(10), ET_CALL, EVENT_INTERVAL, NULL);
 
684
 
 
685
  this_thread()->execute();
 
686
  return 0;
 
687
}