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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
90.0%9100.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::Session class, which manages
  16    :  // the trace file and buffers for a given client of the call trace service.
  17    :  
  18    :  #ifndef SYZYGY_TRACE_SERVICE_SESSION_H_
  19    :  #define SYZYGY_TRACE_SERVICE_SESSION_H_
  20    :  
  21    :  #include <list>
  22    :  #include <map>
  23    :  
  24    :  #include "base/basictypes.h"
  25    :  #include "base/process.h"
  26    :  #include "base/files/file_path.h"
  27    :  #include "base/memory/ref_counted.h"
  28    :  #include "base/memory/scoped_ptr.h"
  29    :  #include "base/synchronization/condition_variable.h"
  30    :  #include "base/synchronization/lock.h"
  31    :  #include "base/win/scoped_handle.h"
  32    :  #include "syzygy/trace/service/buffer_consumer.h"
  33    :  #include "syzygy/trace/service/buffer_pool.h"
  34    :  #include "syzygy/trace/service/process_info.h"
  35    :  
  36    :  namespace trace {
  37    :  namespace service {
  38    :  
  39    :  // Forward declaration.
  40    :  class Service;
  41    :  
  42    :  // Holds all of the data associated with a given client session.
  43    :  // Note that this class it not internally thread safe.  It is expected
  44    :  // that the CallTraceService will ensure that access to a given instance
  45    :  // of this class is synchronized.
  46    :  class Session : public base::RefCountedThreadSafe<Session> {
  47    :   public:
  48    :    typedef base::ProcessId ProcessId;
  49    :  
  50    :    explicit Session(Service* call_trace_service);
  51    :  
  52    :   public:
  53    :    // Initialize this session object.
  54    :    bool Init(ProcessId client_process_id);
  55    :  
  56    :    // Close the session. The causes the session to flush all of its outstanding
  57    :    // buffers to the write queue.
  58    :    bool Close();
  59    :  
  60    :    // Get the next available buffer for use by a client. The session retains
  61    :    // ownership of the buffer object, it MUST not be deleted by the caller. This
  62    :    // may cause new buffers to be allocated if there are no free buffers
  63    :    // available.
  64    :    // @param buffer will be populated with a pointer to the buffer to be provided
  65    :    //     to the client.
  66    :    // @returns true on success, false otherwise.
  67    :    bool GetNextBuffer(Buffer** buffer);
  68    :  
  69    :    // Gets a buffer with a size at least as big as that requested. If the size
  70    :    // is consistent with the common buffer pool, this will be satisfied from
  71    :    // there. Otherwise, it will result in a specific allocation. The buffer
  72    :    // should be returned/recycled in the normal way. Buffers requested in this
  73    :    // method are not specifically subject to throttling and thus should only be
  74    :    // called for large and long lifespan uses.
  75    :    // @param minimum_size the minimum size of the buffer.
  76    :    // @param buffer will be populated with a pointer to the buffer to be provided
  77    :    //     to the client.
  78    :    // @returns true on success, false otherwise.
  79    :    bool GetBuffer(size_t minimum_size, Buffer** out_buffer);
  80    :  
  81    :    // Returns a full buffer back to the session. After being returned here the
  82    :    // session will ensure the buffer gets written to disk before being returned
  83    :    // to service.
  84    :    // @param buffer the full buffer to return.
  85    :    // @returns true on success, false otherwise.
  86    :    bool ReturnBuffer(Buffer* buffer);
  87    :  
  88    :    // Returns a buffer to the pool of available buffers to be handed out to
  89    :    // clients. This is to be called by the write queue thread after the buffer
  90    :    // has been written to disk.
  91    :    // @param buffer the full buffer to recycle.
  92    :    // @returns true on success, false otherwise.
  93    :    bool RecycleBuffer(Buffer* buffer);
  94    :  
  95    :    // Locates the local record of the given call trace buffer.  The session
  96    :    // retains ownership of the buffer object, it MUST not be deleted by the
  97    :    // caller.
  98    :    bool FindBuffer(::CallTraceBuffer* call_trace_buffer,
  99    :                    Buffer** client_buffer);
 100    :  
 101    :    // Returns the process id of the client process.
 102  E :    ProcessId client_process_id() const { return client_.process_id; }
 103    :  
 104    :    // Returns the process information about this session's client.
 105  E :    const ProcessInfo& client_info() const { return client_; }
 106    :  
 107    :    // Get the buffer consumer for this session.
 108  E :    BufferConsumer* buffer_consumer() { return buffer_consumer_; }
 109    :  
 110    :    // Set the buffer consumer for this session.
 111  E :    void set_buffer_consumer(BufferConsumer* consumer) {
 112  E :      DCHECK(consumer != NULL);
 113  E :      DCHECK(buffer_consumer_.get() == NULL);
 114  E :      buffer_consumer_ = consumer;
 115  E :    }
 116    :  
 117    :   protected:
 118    :    friend class base::RefCountedThreadSafe<Session>;
 119    :    virtual ~Session();
 120    :  
 121    :    // @name Testing seams. These are basically events which will be called,
 122    :    //     providing places for unittests to set some hooks.
 123    :    // @{
 124  i :    virtual void OnWaitingForBufferToBeRecycled() { }
 125    :  
 126  E :    virtual void OnDestroySingletonBuffer(Buffer* buffer) { }
 127    :  
 128    :    // Initialize process information for @p process_id.
 129    :    // @param process_id the process we want to capture information for.
 130    :    // @param client the record where we store the captured info.
 131    :    // @returns true on success.
 132    :    // @note does detailed logging on failure.
 133    :    virtual bool InitializeProcessInfo(ProcessId process_id,
 134    :                                       ProcessInfo* client);
 135    :  
 136    :    // Copy a shared memory segment handle to the client process.
 137    :    // @param client_process_handle a valid handle to the client process.
 138    :    // @param local_handle the locally valid handle that's to be duplicated.
 139    :    // @param client_copy on success returns the copied handle.
 140    :    // @returns true on success.
 141    :    // @note does detailed logging on failure.
 142    :    virtual bool CopyBufferHandleToClient(HANDLE client_process_handle,
 143    :                                          HANDLE local_handle,
 144    :                                          HANDLE* client_copy);
 145    :  
 146    :    // @}
 147    :  
 148    :    typedef Buffer::BufferState BufferState;
 149    :    typedef std::list<BufferPool*> SharedMemoryBufferCollection;
 150    :  
 151    :    // Allocates num_buffers shared client buffers, each of size
 152    :    // buffer_size and adds them to the free list.
 153    :    // @param num_nuffers the number of buffers to allocate.
 154    :    // @param buffer_size the size of each buffer to be allocated.
 155    :    // @param pool a pointer to the pool of allocated buffers.
 156    :    // @returns true on success, false otherwise.
 157    :    // @pre Under lock_.
 158    :    bool AllocateBufferPool(
 159    :        size_t num_buffers, size_t buffer_size, BufferPool** out_pool);
 160    :  
 161    :    // Allocates num_buffers shared client buffers, each of size
 162    :    // buffer_size and adds them to the free list.
 163    :    // @param num_nuffers the number of buffers to allocate.
 164    :    // @param buffer_size the size of each buffer to be allocated.
 165    :    // @returns true on success, false otherwise.
 166    :    // @pre Under lock_.
 167    :    // @note this is virtual to provide a testing seam.
 168    :    virtual bool AllocateBuffers(size_t num_buffers, size_t buffer_size);
 169    :  
 170    :    // Allocates a buffer for immediate use, not releasing it to the common buffer
 171    :    // pool and signaling its availability.
 172    :    // @param minimum_size the minimum size of the buffer.
 173    :    // @param out_buffer will be set to point to the newly allocated buffer.
 174    :    // @pre Under lock_.
 175    :    // @pre minimum_size must be bigger than the common buffer allocation size.
 176    :    bool AllocateBufferForImmediateUse(size_t minimum_size, Buffer** out_buffer);
 177    :  
 178    :    // A private implementation of GetNextBuffer, but which assumes the lock has
 179    :    // already been acquired.
 180    :    // @param buffer will be populated with a pointer to the buffer to be provided
 181    :    //     to the client.
 182    :    // @returns true on success, false otherwise.
 183    :    // @pre Under lock_.
 184    :    bool GetNextBufferUnlocked(Buffer** buffer);
 185    :  
 186    :    // Destroys the given buffer, and its containing pool. The buffer must be the
 187    :    // only buffer in its pool, and must be in the pending write state. This is
 188    :    // meant for destroying singleton buffers that have been allocated with
 189    :    // custom sizes. We don't want to return them to the general pool.
 190    :    // @param buffer the buffer whose pool is to be destroyed.
 191    :    // @returns true on success, false otherwise.
 192    :    // @pre buffer is in the 'pending write' state. It should already have been
 193    :    //     written but not yet transitioned.
 194    :    // @pre buffer is a singleton. That is, is part of a pool that contains only
 195    :    //     a single buffer.
 196    :    bool DestroySingletonBuffer(Buffer* buffer);
 197    :  
 198    :    // Transitions the buffer to the given state. This only updates the buffer's
 199    :    // internal state and buffer_state_counts_, but not buffers_available_.
 200    :    // DCHECKs on any attempted invalid state changes.
 201    :    // @param new_state the new state to be applied to the buffer.
 202    :    // @param buffer the buffer to have its state changed.
 203    :    // @pre Under lock_.
 204    :    void ChangeBufferState(BufferState new_state, Buffer* buffer);
 205    :  
 206    :    // Gets (creating if needed) a buffer and populates it with a
 207    :    // TRACE_PROCESS_ENDED event. This is called by Close(), which is called
 208    :    // when the process owning this session disconnects (at its death).
 209    :    // @param buffer receives a pointer to the buffer that is used.
 210    :    // @returns true on success, false otherwise.
 211    :    // @pre Under lock_.
 212    :    bool CreateProcessEndedEvent(Buffer** buffer);
 213    :  
 214    :    // Returns true if the buffer book-keeping is self-consistent.
 215    :    // @pre Under lock_.
 216    :    bool BufferBookkeepingIsConsistent() const;
 217    :  
 218    :    // The call trace service this session lives in.  We do not own this
 219    :    // object.
 220    :    Service* const call_trace_service_;
 221    :  
 222    :    // The process information for the client to which the session belongs.
 223    :    ProcessInfo client_;
 224    :  
 225    :    // All shared memory buffers allocated for this session.
 226    :    SharedMemoryBufferCollection shared_memory_buffers_;  // Under lock_.
 227    :  
 228    :    // This is the set of buffers that we currently own.
 229    :    typedef std::map<Buffer::ID, Buffer*> BufferMap;
 230    :    BufferMap buffers_;  // Under lock_.
 231    :  
 232    :    // State summary.
 233    :    size_t buffer_state_counts_[Buffer::kBufferStateMax];  // Under lock_.
 234    :  
 235    :    // The consumer responsible for processing this sessions buffers. The
 236    :    // lifetime of this object is managed by the call trace service.
 237    :    scoped_refptr<BufferConsumer> buffer_consumer_;
 238    :  
 239    :    // Buffers available to give to the clients.
 240    :    typedef std::deque<Buffer*> BufferQueue;
 241    :    BufferQueue buffers_available_;  // Under lock_.
 242    :  
 243    :    // Tracks whether this session is in the process of shutting down.
 244    :    bool is_closing_;  // Under lock_.
 245    :  
 246    :    // This is used to count the number of GetNextBuffer requests that are
 247    :    // currently applying back-pressure. There can only be as many of them as
 248    :    // there are buffers to be recycled until we fall below the back-pressure cap.
 249    :    size_t buffer_requests_waiting_for_recycle_;  // Under lock_.
 250    :  
 251    :    // This condition variable is used to indicate that a buffer is available.
 252    :    base::ConditionVariable buffer_is_available_;  // Under lock_.
 253    :  
 254    :    // This is currently only used to allocate unique IDs to buffers allocated
 255    :    // after the session closes.
 256    :    // TODO(rogerm): extend this to all buffers.
 257    :    size_t buffer_id_;  // Under lock_.
 258    :  
 259    :    // This lock protects any access to the internals related to buffers and their
 260    :    // state.
 261    :    base::Lock lock_;
 262    :  
 263    :    // Tracks whether or not invalid input errors have already been logged.
 264    :    // When an error of this type occurs, there will typically be numerous
 265    :    // follow-on occurrences that we don't want to log.
 266    :    bool input_error_already_logged_;  // Under lock_.
 267    :  
 268    :   private:
 269    :    DISALLOW_COPY_AND_ASSIGN(Session);
 270    :  };
 271    :  
 272    :  }  // namespace service
 273    :  }  // namespace trace
 274    :  
 275    :  #endif  // SYZYGY_TRACE_SERVICE_SESSION_H_

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