Sirikata
|
00001 /* Sirikata 00002 * Trace.hpp 00003 * 00004 * Copyright (c) 2009, Ewen Cheslack-Postava 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are 00009 * met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * * Neither the name of Sirikata nor the names of its contributors may 00017 * be used to endorse or promote products derived from this software 00018 * without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00021 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00022 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00023 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00024 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 */ 00032 00033 #ifndef _SIRIKATA_CORE_TRACE_HPP_ 00034 #define _SIRIKATA_CORE_TRACE_HPP_ 00035 00036 #include <sirikata/core/util/Platform.hpp> 00037 #include <sirikata/core/util/Thread.hpp> 00038 #include <sirikata/core/util/AtomicTypes.hpp> 00039 #include <sirikata/core/network/ObjectMessage.hpp> 00040 #include <sirikata/core/trace/BatchedBuffer.hpp> 00041 00042 namespace Sirikata { 00043 namespace Trace { 00044 00045 #define TRACE_DROP(nam) ((mContext->trace()->drops.n[::Sirikata::Trace::Drops::nam]=#nam )&&++(mContext->trace()->drops.d[::Sirikata::Trace::Drops::nam])); SILOG(drop,insane,#nam) 00046 00047 struct Drops { 00048 enum { 00049 OH_DROPPED_AT_SEND, 00050 OH_DROPPED_AT_RECEIVE_QUEUE, 00051 SPACE_DROPPED_AT_MAIN_STRAND_CROSSING, 00052 DROPPED_AT_FORWARDED_LOCALLY, 00053 DROPPED_DURING_FORWARDING, 00054 DROPPED_DURING_FORWARDING_ROUTING, 00055 DROPPED_AT_SPACE_ENQUEUED, 00056 DROPPED_CSFQ_OVERFLOW, 00057 DROPPED_CSFQ_PROBABILISTIC, 00058 NUM_DROPS 00059 }; 00060 uint64 d[NUM_DROPS]; 00061 const char*n[NUM_DROPS]; 00062 Drops() { 00063 memset(d,0,NUM_DROPS*sizeof(uint64)); 00064 memset(n,0,NUM_DROPS*sizeof(const char*)); 00065 } 00066 void output(); 00067 }; 00068 00069 #define ProximityTag 0 00070 #define ObjectLocationTag 1 00071 #define ServerDatagramQueuedTag 4 00072 #define ServerDatagramSentTag 5 00073 #define ServerDatagramReceivedTag 6 00074 #define SegmentationChangeTag 10 00075 00076 #define MigrationBeginTag 11 00077 #define MigrationAckTag 12 00078 #define MigrationRoundTripTag 18 00079 00080 #define ServerLocationTag 13 00081 #define ServerObjectEventTag 14 00082 #define ObjectSegmentationCraqLookupRequestAnalysisTag 15 00083 #define ObjectSegmentationProcessedRequestAnalysisTag 16 00084 #define ObjectPingTag 17 00085 #define ObjectPingCreatedTag 32 00086 #define ObjectHitPointTag 34 00087 00088 #define OSegTrackedSetResultAnalysisTag 19 00089 #define OSegShutdownEventTag 20 00090 #define ObjectGeneratedLocationTag 22 00091 #define OSegCacheResponseTag 23 00092 #define OSegLookupNotOnServerAnalysisTag 24 00093 #define OSegCumulativeTraceAnalysisTag 25 00094 #define MessageTimestampTag 30 00095 #define MessageCreationTimestampTag 31 00096 00097 #define ObjectConnectedTag 33 00098 00099 enum MessagePath { 00100 NONE, // Used when tag is needed but we don't have a name for it 00101 00102 // Object Host Checkpoints 00103 CREATED, 00104 DESTROYED, 00105 OH_HIT_NETWORK, 00106 OH_DROPPED_AT_SEND, 00107 OH_NET_RECEIVED, 00108 OH_DROPPED_AT_RECEIVE_QUEUE, 00109 OH_RECEIVED, 00110 SPACE_DROPPED_AT_MAIN_STRAND_CROSSING, 00111 // Space Checkpoints 00112 HANDLE_OBJECT_HOST_MESSAGE, 00113 HANDLE_SPACE_MESSAGE, 00114 00115 FORWARDED_LOCALLY, 00116 DROPPED_AT_FORWARDED_LOCALLY, 00117 00118 FORWARDING_STARTED, 00119 00120 FORWARDED_LOCALLY_SLOW_PATH, 00121 00122 // FIXME could follow FORWARDED_LOCALLY_SLOW_PATH or OSEG_LOOKUP_STARTED 00123 DROPPED_DURING_FORWARDING, 00124 00125 OSEG_CACHE_CHECK_STARTED, 00126 OSEG_CACHE_CHECK_FINISHED, 00127 00128 OSEG_LOOKUP_STARTED, 00129 OSEG_CACHE_LOOKUP_FINISHED, 00130 OSEG_SERVER_LOOKUP_FINISHED, 00131 OSEG_LOOKUP_FINISHED, 00132 00133 SPACE_TO_SPACE_ENQUEUED, 00134 DROPPED_AT_SPACE_ENQUEUED, 00135 00136 SPACE_TO_SPACE_HIT_NETWORK, 00137 00138 SPACE_TO_SPACE_READ_FROM_NET, 00139 SPACE_TO_SPACE_SMR_DEQUEUED, 00140 00141 SPACE_TO_OH_ENQUEUED, 00142 00143 NUM_PATHS 00144 }; 00145 00146 class SIRIKATA_EXPORT Trace { 00147 public: 00148 Drops drops; 00149 00150 ~Trace(); 00151 00152 // Initialize options which flip recording of trace data on and off 00153 static void InitOptions(); 00154 00155 Trace(const String& filename); 00156 00157 00158 #define CREATE_TRACE_CHECK_DECL(___name) \ 00159 bool check ## ___name () const; 00160 #define CREATE_TRACE_EVAL_DECL(___name, ...) \ 00161 void ___name( __VA_ARGS__ ); 00162 00163 #define CREATE_TRACE_DECL(___name, ...) \ 00164 CREATE_TRACE_CHECK_DECL(___name) \ 00165 CREATE_TRACE_EVAL_DECL(___name, __VA_ARGS__) 00166 00167 00168 00169 // This macro simplifies creating the methods that check if we should actually 00170 // perform the trace. 00171 #define CREATE_TRACE_CHECK_DEF(__klass, ___name , ___log_var) \ 00172 bool __klass :: check ## ___name () const { \ 00173 return ___log_var->as<bool>(); \ 00174 } 00175 00176 #define CREATE_TRACE_EVAL_DEF(__klass, ___name , ... ) \ 00177 void __klass :: ___name ( __VA_ARGS__ ) 00178 00179 // This macro takes care of everything -- just specify the name, the 00180 // OptionValue* to check, argument types, and then follow it with the body. 00181 #define CREATE_TRACE_DEF(__klass, ___name , ___log_var, ... ) \ 00182 CREATE_TRACE_CHECK_DEF(__klass, ___name, ___log_var) \ 00183 CREATE_TRACE_EVAL_DEF(__klass, ___name, __VA_ARGS__) 00184 00185 00186 CREATE_TRACE_DECL(timestampMessageCreation, const Time&t, uint64 packetId, MessagePath path, ObjectMessagePort optionalMessageSourcePort=0, ObjectMessagePort optionalMessageDestPort=0); 00187 CREATE_TRACE_DECL(timestampMessage, const Time&t, uint64 packetId, MessagePath path); 00188 00189 00190 // Helper to prepend framing (size and payload type hint) 00191 void writeRecord(uint16 type_hint, BatchedBuffer::IOVec* data, uint32 iovcnt); 00192 00193 // Helper to prepend framing (size and payload type hint) 00194 template<typename T> 00195 void writeRecord(uint16 type_hint, const T& pl) { 00196 if (mShuttingDown) return; 00197 00198 std::string serialized_pl; 00199 bool serialized_success = pl.SerializeToString(&serialized_pl); 00200 assert(serialized_success); 00201 00202 const uint32 num_data = 1; 00203 BatchedBuffer::IOVec data_vec[num_data] = { 00204 BatchedBuffer::IOVec(&(serialized_pl[0]), serialized_pl.size()) 00205 }; 00206 writeRecord(type_hint, data_vec, num_data); 00207 } 00208 00209 00210 public: 00211 00212 void prepareShutdown(); 00213 void shutdown(); 00214 00215 private: 00216 // Thread which flushes data to disk periodically 00217 void storageThread(const String& filename); 00218 00219 BatchedBuffer data; 00220 bool mShuttingDown; 00221 00222 Thread* mStorageThread; 00223 Sirikata::AtomicValue<bool> mFinishStorage; 00224 00225 // OptionValues that turn tracing on/off 00226 static OptionValue* mLogMessage; 00227 }; // class Trace 00228 00229 } // namespace Trace 00230 00231 // This is how you should *actually* 00232 #define TRACE(___trace, ___name, ...) \ 00233 { \ 00234 if ( ___trace-> check ## ___name () ) \ 00235 ___trace-> ___name ( __VA_ARGS__ ); \ 00236 } while(0) 00237 // To check that you aren't using tracing via the incorrect interface (that is, 00238 // directly instead of via macros) uncomment the following and mark the DECL's 00239 // in Trace as private. 00240 //#undef TRACE 00241 //#define TRACE(___trace, ___name, ...) 00242 00243 // This version of the TRACE macro automatically uses mContext->trace() and 00244 // passes mContext->simTime() as the first argument, which is the most common 00245 // form. 00246 #define CONTEXT_TRACE(___name, ...) \ 00247 TRACE( mContext->trace(), ___name, mContext->simTime(), __VA_ARGS__) 00248 00249 // This version is like the above, but you can specify the time yourself. Use 00250 // this if you already called Context::simTime() recently. (It also works for 00251 // cases where the first parameter is not the current time.) 00252 #define CONTEXT_TRACE_NO_TIME(___name, ...) \ 00253 TRACE( mContext->trace(), ___name, __VA_ARGS__) 00254 00255 } // namespace Sirikata 00256 00257 00258 00259 00260 #ifdef CBR_TIMESTAMP_PACKETS 00261 // The most complete macro, allows you to specify everything 00262 #define TIMESTAMP_FULL(trace, time, packetId, path) TRACE(trace, timestampMessage, time, packetId, path) 00263 00264 // Slightly simplified version, works everywhere mContext->trace() and mContext->simTime() are valid 00265 #define TIMESTAMP_SIMPLE(packetId, path) TIMESTAMP_FULL(mContext->trace(), mContext->simTime(), packetId, path) 00266 00267 // Further simplified version, works as long as packet is a valid pointer to a packet at the time this is called 00268 #define TIMESTAMP(packet, path) TIMESTAMP_SIMPLE(packet->unique(), path) 00269 00270 // In cases where you need to split the time between recording the info for a timestamp and actually performing 00271 // the timestamp, use a _START _END combination. Generally this should only be needed if you are timestamping 00272 // after a message might be deleted or is out of your control (e.g. you pushed onto a queue or destroyed it). 00273 #define TIMESTAMP_START(prefix, packet) \ 00274 Sirikata::uint64 prefix ## _uniq = packet->unique(); 00275 00276 #define TIMESTAMP_END(prefix, path) TIMESTAMP_SIMPLE(prefix ## _uniq, path) 00277 00278 // When the message has been wrapped in a space node -> space node message, we 00279 // need to use a special form, using the payload_id recorded in that message's 00280 // header 00281 #define TIMESTAMP_PAYLOAD(packet, path) TIMESTAMP_SIMPLE(packet->payload_id(), path) 00282 00283 #define TIMESTAMP_PAYLOAD_START(prefix, packet) \ 00284 Sirikata::uint64 prefix ## _uniq = packet->payload_id(); 00285 00286 #define TIMESTAMP_PAYLOAD_END(prefix, path) TIMESTAMP_SIMPLE(prefix ## _uniq, path) 00287 00288 00289 #define TIMESTAMP_CREATED(packet, path) TRACE(mContext->trace(), timestampMessageCreation, mContext->simTime(), packet->unique(), path, packet->source_port(), packet->dest_port()) 00290 00291 #else //CBR_TIMESTAMP_PACKETS 00292 #define TIMESTAMP_FULL(trace, time, packetId, path) 00293 #define TIMESTAMP_SIMPLE(packetId, path) 00294 #define TIMESTAMP(packet, path) 00295 #define TIMESTAMP_START(prefix, packet) 00296 #define TIMESTAMP_END(prefix, path) 00297 #define TIMESTAMP_PAYLOAD(packet, path) 00298 #define TIMESTAMP_PAYLOAD_START(prefix, packet) 00299 #define TIMESTAMP_PAYLOAD_END(prefix, path) 00300 #define TIMESTAMP_CREATED(packet, path) 00301 #endif //CBR_TIMESTAMP_PACKETS 00302 00303 #endif //_SIRIKATA_STATISTICS_HPP_