4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <inj_event.h>
34 #include <fm/fmd_log.h>
36 typedef struct inj_logfile
{
37 uint64_t ilf_sec
; /* timestamp seconds from previous record */
38 uint64_t ilf_nsec
; /* timestamp nanoseconds from previous record */
39 int ilf_index
; /* record index in log file for fake lineno */
44 inj_logfile_event(fmd_log_t
*lp
, const fmd_log_record_t
*rp
, void *data
)
46 inj_cmd_t
*cmd
= inj_zalloc(sizeof (inj_cmd_t
));
47 inj_defn_t
*ev
= inj_zalloc(sizeof (inj_defn_t
));
49 hrtime_t rec_sec
= rp
->rec_sec
+ rp
->rec_nsec
/ NANOSEC
;
50 hrtime_t rec_nsec
= rp
->rec_nsec
% NANOSEC
;
52 inj_logfile_t
*ilf
= data
;
55 if (ilf
->ilf_index
== 1)
56 goto add_event
; /* do not try to adjust time for first record */
59 * If the current record's time is before that of the previous record,
60 * advance it to the previous record time. This may occur when delays
61 * between capturing ENA and enqueuing a sysevent are observed.
63 if (rec_sec
< ilf
->ilf_sec
||
64 (rec_sec
== ilf
->ilf_sec
&& rec_nsec
< ilf
->ilf_nsec
)) {
65 warn("record [%d] (%s) timestamp is out of order: "
66 "advancing event time to %llx.%llx\n",
67 ilf
->ilf_index
, rp
->rec_class
, ilf
->ilf_sec
, ilf
->ilf_nsec
);
68 rec_sec
= ilf
->ilf_sec
;
69 rec_nsec
= ilf
->ilf_nsec
;
73 * For now, compute the delta between the previous record and this one
74 * as a number of nanoseconds and advance the clock. If a massively
75 * large delay is observed (>INT64_MAX ns), we abort. This could be
76 * improved if necessary by sending more than one cmd_addhrt in a loop.
78 delta
= (rec_sec
- ilf
->ilf_sec
) * NANOSEC
;
79 delta
+= (hrtime_t
)rec_nsec
- (hrtime_t
)ilf
->ilf_nsec
;
82 die("record [%d] timestamp delta too large\n", ilf
->ilf_index
);
85 inj_cmds_add(inj_cmd_addhrt(delta
));
88 ev
->defn_name
= inj_strdup(rp
->rec_class
);
89 ev
->defn_lineno
= ilf
->ilf_index
++;
91 if ((errno
= nvlist_dup(rp
->rec_nvl
, &ev
->defn_nvl
, 0)) != 0)
92 die("failed to allocate nvl for %s event", rp
->rec_class
);
94 cmd
->cmd_type
= CMD_SEND_EVENT
;
99 ilf
->ilf_sec
= rec_sec
;
100 ilf
->ilf_nsec
= rec_nsec
;
106 inj_logfile_read(fmd_log_t
*lp
)
108 const char *label
= fmd_log_label(lp
);
111 if (strcmp(label
, "error") != 0)
112 die("cannot use '%s' log as injector input\n", label
);
114 bzero(&ilf
, sizeof (ilf
));
117 if (fmd_log_iter(lp
, inj_logfile_event
, &ilf
) != 0) {
118 die("failed to process log: %s\n",
119 fmd_log_errmsg(lp
, fmd_log_errno(lp
)));
122 return (inj_cmds_get());