/** * ========================================================================= * File : trace.h * Project : 0 A.D. * Description : allows recording and 'playing back' a sequence of * : I/Os - useful for benchmarking and archive builder. * * @author Jan.Wassenberg@stud.uni-karlsruhe.de * ========================================================================= */ /* * Copyright (c) 2006 Jan Wassenberg * * Redistribution and/or modification are also permitted under the * terms of the GNU General Public License as published by the * Free Software Foundation (version 2 or later, at your option). * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef TRACE_H__ #define TRACE_H__ namespace ERR { const LibError TRACE_EMPTY = -110500; } extern void trace_enable(bool want_enabled); extern void trace_shutdown(); extern void trace_notify_io(const char* P_fn, size_t size, uint flags); extern void trace_notify_free(const char* P_fn, size_t size); // TraceEntry operation type. // note: rather than only a list of accessed files, we also need to // know the application's behavior WRT caching (e.g. when it releases // cached buffers). this is necessary so that our simulation can // yield the same behavior. enum TraceOp { TO_IO, TO_FREE, }; // stores one event that is relevant for file IO / caching. // // size-optimized a bit since these are all kept in memory // (to prevent trace file writes from affecting other IOs) struct TraceEntry { // note: float instead of double for nice 16 byte struct size float timestamp; // returned by get_time before operation starts const char* atom_fn; // path+name of affected file // rationale: store size in the trace because other applications // that use this trace format but not our IO code wouldn't know // size (since they cannot retrieve the file info given atom_fn). size_t size; // of IO (usually the entire file) uint op : 8; // operation - see TraceOp uint flags : 24; // misc, e.g. file_io flags. }; struct TraceRun { const TraceEntry* ents; size_t num_ents; }; struct Trace { // most recent first! (see rationale in source) const TraceRun* runs; size_t num_runs; size_t total_ents; }; extern void trace_get(Trace* t); extern LibError trace_write_to_file(const char* trace_filename); extern LibError trace_read_from_file(const char* trace_filename, Trace* t); extern void trace_gen_random(size_t num_entries); // simulate carrying out the entry's TraceOp to determine // whether this IO would be satisfied by the file_buf cache. extern bool trace_entry_causes_io(const TraceEntry* ent); enum TraceRunFlags { TRF_SYNC_TO_TIMESTAMP = 1 }; // carry out all operations specified in the trace. // if flags&TRF_SYNC_TO_TIMESTAMP, waits until timestamp for each event is // reached; otherwise, they are run as fast as possible. extern LibError trace_run(const char* trace_filename, uint flags = 0); #endif // #ifndef TRACE_H__