Coverage for /Syzygy/trace/service/service.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
88.0%22250.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  // This file declares the trace::service::Service class which implements
  16    :  // the call trace service RPC interface.
  17    :  
  18    :  #ifndef SYZYGY_TRACE_SERVICE_SERVICE_H_
  19    :  #define SYZYGY_TRACE_SERVICE_SERVICE_H_
  20    :  
  21    :  #include <map>
  22    :  
  23    :  #include "base/basictypes.h"
  24    :  #include "base/process.h"
  25    :  #include "base/string_piece.h"
  26    :  #include "base/files/file_path.h"
  27    :  #include "base/memory/ref_counted.h"
  28    :  #include "base/synchronization/condition_variable.h"
  29    :  #include "base/threading/platform_thread.h"
  30    :  #include "base/threading/thread.h"
  31    :  #include "syzygy/trace/rpc/call_trace_rpc.h"
  32    :  
  33    :  namespace trace {
  34    :  namespace service {
  35    :  
  36    :  // Forward declarations.
  37    :  class BufferConsumerFactory;
  38    :  class Session;
  39    :  
  40    :  // Implements the CallTraceService interface (see "call_trace_rpc.idl".
  41    :  // For the most basic usage:
  42    :  //
  43    :  //   trace::service::Service::Instance().Start(false);
  44    :  //
  45    :  // This will access and launch a static instance of the service using a
  46    :  // default configuration. Specifying false, as in the above example,
  47    :  // will cause the call to be blocking; the call will not return until
  48    :  // the service is shutdown via the RequestShutdown() method. Specifying
  49    :  // true for the parameter to Start() will cause the Start() method to
  50    :  // return immediately, running the service in the background.
  51    :  //
  52    :  // Some mechanism to trigger a call to RequestShutdown() should be
  53    :  // provided to the operator of the service; for example, a signal handler
  54    :  // on SIGINT and/or SIGTERM, an event listening listening for a shutdown
  55    :  // Message, an IO loop waiting on a socket or Event, etc. The service
  56    :  // can also stopped remotely via an RPC call to CallTraceControl::Stop().
  57    :  class Service {
  58    :   public:
  59    :    typedef base::ProcessId ProcessId;
  60    :  
  61    :    // Flag passed to CommitAndExchangeBuffer() to determine whether or
  62    :    // not a fresh buffer should be returned to the client.
  63    :    enum ExchangeFlag {
  64    :      DO_NOT_PERFORM_EXCHANGE,
  65    :      PERFORM_EXCHANGE
  66    :    };
  67    :  
  68    :    // Construct a new call trace Service instance. The service will use the
  69    :    // given @p factory to construct buffer consumers for new sessions. The
  70    :    // service instance does NOT take ownership of the @p factory, which must
  71    :    // exist at least until the service instance is destroyed.
  72    :    explicit Service(BufferConsumerFactory* factory);
  73    :    ~Service();
  74    :  
  75    :    // The default number of buffers to allocate when expanding the buffer
  76    :    // pool allocated for a given client session.
  77    :    static const size_t kDefaultNumIncrementalBuffers;
  78    :  
  79    :    // The default size (in bytes) for each call trace buffer.
  80    :    static const size_t kDefaultBufferSize;
  81    :  
  82    :    // The default maximum number of buffers pending write that a session should
  83    :    // allow before beginning to force writes.
  84    :    static const size_t kDefaultMaxBuffersPendingWrite;
  85    :  
  86    :    // Set the id for this instance.
  87  E :    void set_instance_id(const base::StringPiece16& id) {
  88  E :      DCHECK(!is_running());
  89  E :      instance_id_.assign(id.begin(), id.end());
  90  E :    }
  91    :  
  92    :    // Set the trace flags that get communicated to clients on session creation.
  93    :    // The flags value should be bitmask composed of the values from the
  94    :    // TraceEventType enumeration (see call_trace_defs.h).
  95    :    //
  96    :    // @note TRACE_FLAG_BATCH_ENTER is mutually exclusive with all other flags.
  97    :    //     If TRACE_FLAG_BATCH_ENTER is set, all other flags will be ignored.
  98  i :    void set_flags(uint32 flags) {
  99  i :      flags_ = flags;
 100  i :    }
 101    :  
 102    :    // Set the number of buffers by which to grow a sessions
 103    :    // buffer pool.
 104  E :    void set_num_incremental_buffers(size_t n) {
 105  E :      num_incremental_buffers_ = n;
 106  E :    }
 107    :  
 108    :    // Set the number of bytes comprising each buffer in a
 109    :    // sessions buffer pool.
 110  E :    void set_buffer_size_in_bytes(size_t n) {
 111  E :      buffer_size_in_bytes_ = n;
 112  E :    }
 113    :  
 114    :    // Sets the maximum number of buffers pending write that a session should
 115    :    // allow before starting to force buffer writes.
 116    :    // @param n the max number of buffers pending write to allow.
 117  E :    void set_max_buffers_pending_write(size_t n) {
 118  E :      DCHECK_LT(0u, n);
 119  E :      max_buffers_pending_write_ = n;
 120  E :    }
 121    :  
 122    :    // @returns the number of new buffers to be created per allocation.
 123  E :    size_t num_incremental_buffers() const { return num_incremental_buffers_; }
 124    :  
 125    :    // @returns the size (in bytes) of new buffers to be allocated.
 126  E :    size_t buffer_size_in_bytes() const { return buffer_size_in_bytes_; }
 127    :  
 128    :    // @returns the maximum number of buffers that sessions should allow to be
 129    :    //     pending writes prior to starting to force them.
 130  E :    size_t max_buffers_pending_write() const {
 131  E :      return max_buffers_pending_write_;
 132  E :    }
 133    :  
 134    :    // Returns true if any of the service's subsystems are running.
 135  E :    bool is_running() const {
 136  E :      return rpc_is_running_ || num_active_sessions_ > 0;
 137  E :    }
 138    :  
 139    :    // Begin accepting and handling RPC invocations. This method is not
 140    :    // generally callable by clients of the service; it may only be called
 141    :    // by the thread which created the service.
 142    :    //
 143    :    // The request handlers will be run on a thread pool owned by the RPC
 144    :    // runtime. If the non_blocking parameter is true, the call to Start()
 145    :    // will return immediately, allowing the owning thread to perform other
 146    :    // work while the service runs in the background. If non_blocking is
 147    :    // false, then the call to Start() will only return when the service
 148    :    // receives a shutdown request (via the RequestShutdown() method).
 149    :    //
 150    :    // Following the receipt of a shutdown request, it is the responsibility of
 151    :    // the thread which owns the service to call Stop() on the service, which
 152    :    // will take care of concluding any in-flight requests and flushing all
 153    :    // outstanding call trace buffers to disk.
 154    :    bool Start(bool non_blocking);
 155    :  
 156    :    // Completely shutdown the service. This method is not generally callable
 157    :    // by clients of the service; it may only be called by the thread which
 158    :    // created, and subsequently started, the service.
 159    :    //
 160    :    // Following the receipt of a shutdown request, it is the responsibility of
 161    :    // the thread which owns the service to call Stop() on the service, which
 162    :    // will take care of concluding any in-flight requests and flushing all
 163    :    // outstanding call trace buffers to disk.
 164    :    //
 165    :    // This is a blocking call, it will return after all outstanding requests
 166    :    // have been handled, all call trace buffers have been flushed, all
 167    :    // sessions have been closed, and all session resources deallocated.
 168    :    bool Stop();
 169    :  
 170    :    // RPC implementation of CallTraceControl::Stop().
 171    :    // See call_trace_rpc.idl for further info.
 172    :    bool RequestShutdown();
 173    :  
 174    :    // RPC implementation of CallTraceService::CreateSession().
 175    :    // See call_trace_rpc.idl for further info.
 176    :    bool CreateSession(handle_t binding,
 177    :                       SessionHandle* session_handle,
 178    :                       CallTraceBuffer* call_trace_buffer,
 179    :                       unsigned long* flags);
 180    :  
 181    :    // RPC implementation of CallTraceService::AllocateBuffer().
 182    :    // See call_trace_rpc.idl for further info.
 183    :    bool AllocateBuffer(SessionHandle session_handle,
 184    :                        CallTraceBuffer* call_trace_buffer);
 185    :  
 186    :    // RPC implementation of CallTraceService::AllocateLargeBuffer().
 187    :    // See call_trace_rpc.idl for further info.
 188    :    bool AllocateLargeBuffer(SessionHandle session_handle,
 189    :                             size_t minimum_size,
 190    :                             CallTraceBuffer* call_trace_buffer);
 191    :  
 192    :    // RPC implementation of both CallTraceService::ExchangeBuffer()
 193    :    // and CallTraceService::ReturnBuffer(). See call_trace_rpc.idl
 194    :    // for further info.
 195    :    bool CommitAndExchangeBuffer(SessionHandle session_handle,
 196    :                                 CallTraceBuffer* call_trace_buffer,
 197    :                                 ExchangeFlag perform_exchange);
 198    :  
 199    :    // RPC implementation of CallTraceService::CloseSession().
 200    :    // See call_trace_rpc.idl for further info.
 201    :    bool CloseSession(SessionHandle* session_handle);
 202    :  
 203    :    // Decrement the active session count.
 204    :    // @see num_active_sessions_
 205    :    void RemoveOneActiveSession();
 206    :  
 207    :    // Increment the active session count.
 208    :    // @see num_active_sessions_.
 209    :    void AddOneActiveSession();
 210    :  
 211    :   // These are protected for unittesting.
 212    :   protected:
 213    :  
 214    :    // @name RPC Server Management Functions.
 215    :    // These functions, unless otherwise noted, are single threaded and must
 216    :    // all be called from the thread that created this instance.
 217    :    // @{
 218    :    bool OpenServiceEvent();
 219    :    bool AcquireServiceMutex();
 220    :    void ReleaseServiceMutex();
 221    :    bool InitializeRpc();
 222    :    bool RunRPC(bool non_blocking);
 223    :  
 224    :    // This function is thread-safe.
 225    :    void StopRpc();
 226    :    void CleanupRpc();
 227    :    // @}
 228    :  
 229    :    // Creates a new session, returning true on success. On failure, the value
 230    :    // of *session will be NULL; otherwise it will contain a Session reference.
 231    :    bool GetNewSession(ProcessId client_process_id,
 232    :                       scoped_refptr<Session>* session);
 233    :  
 234    :    // Looks up an existing session, returning true on success. On failure,
 235    :    // the value of *session will be NULL; otherwise it will contain a
 236    :    // Session reference.
 237    :    bool GetExistingSession(SessionHandle session_handle,
 238    :                            scoped_refptr<Session>* session);
 239    :    // Looks up an existing session, returning true on success. On failure,
 240    :    // the value of *session will be NULL; otherwise it will contain a
 241    :    // Session reference.
 242    :    bool GetExistingSessionUnlocked(SessionHandle session_handle,
 243    :                                    scoped_refptr<Session>* session);
 244    :  
 245    :    // Closes all open sessions. This call blocks until all sessions have been
 246    :    // shutdown and have finished flushing their buffers.
 247    :    bool CloseAllOpenSessions();
 248    :  
 249    :    // Session factory. This is virtual for testing purposes.
 250    :    virtual Session* CreateSession();
 251    :  
 252    :    // Protects concurrent access to the internals, except for write-queue
 253    :    // related internals.
 254    :    base::Lock lock_;
 255    :  
 256    :    // The collection of open trace sessions. This is the collection of sessions
 257    :    // for which the service is currently accepting requests. Once a session is
 258    :    // closed, it is removed from this collection, but may still be active for
 259    :    // some time as it's trace buffers are consumed. See num_active_sessions_.
 260    :    typedef std::map<ProcessId, scoped_refptr<Session>> SessionMap;
 261    :    SessionMap sessions_;  // Under lock_.
 262    :  
 263    :    // A count of the number of active sessions currently managed by this service.
 264    :    // This includes both open sessions and closed sessions which have not yet
 265    :    // finished flushing their buffers.
 266    :    size_t num_active_sessions_;  // Under lock_.
 267    :  
 268    :    // The instance id to use when running this service instance.
 269    :    std::wstring instance_id_;
 270    :  
 271    :    // The number of buffers to allocate with each increment.
 272    :    size_t num_incremental_buffers_;
 273    :  
 274    :    // The number of bytes in each buffer.
 275    :    size_t buffer_size_in_bytes_;
 276    :  
 277    :    // The maximum number of buffers that a session should have pending write.
 278    :    size_t max_buffers_pending_write_;
 279    :  
 280    :    // Handle to the thread that owns/created this call trace service instance.
 281    :    base::PlatformThreadId owner_thread_;
 282    :  
 283    :    // The source factory for buffer consumer objects.
 284    :    BufferConsumerFactory* buffer_consumer_factory_;
 285    :  
 286    :    // Used to wait for all sessions to be closed on service shutdown.
 287    :    base::ConditionVariable a_session_has_closed_;  // Under lock_.
 288    :  
 289    :    // Used to detect whether multiple instances of the service are running
 290    :    // against the service endpoint.
 291    :    base::win::ScopedHandle service_mutex_;
 292    :  
 293    :    // Signaled once the service has successfully initialized.
 294    :    base::win::ScopedHandle service_event_;
 295    :  
 296    :    // Flags denoting the state of the RPC server.
 297    :    bool rpc_is_initialized_;
 298    :    // TODO(rogerm): Access to this flag is inconsistent, but it seems the
 299    :    //    transition from true to false will always take place under lock_.
 300    :    bool rpc_is_running_;  // Under lock_.
 301    :    bool rpc_is_non_blocking_;
 302    :  
 303    :    // Flags informing the client of what trace events the service would like
 304    :    // to receive.
 305    :    uint32 flags_;
 306    :  
 307    :   private:
 308    :    DISALLOW_COPY_AND_ASSIGN(Service);
 309    :  };
 310    :  
 311    :  }  // namespace service
 312    :  }  // namespace trace
 313    :  
 314    :  #endif  // SYZYGY_TRACE_SERVICE_SERVICE_H_

Coverage information generated Thu Jul 04 09:34:53 2013.