content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   *
   */
  package org.apache.cassandra.tracing;
  
  import java.net.InetAddress;
  import java.nio.ByteBuffer;
  import java.util.Map;
  
  import org.apache.cassandra.concurrent.Stage;
  import org.apache.cassandra.locator.InetAddressAndPort;
  import org.apache.cassandra.utils.TimeUUID;
  import org.apache.cassandra.utils.WrappedRunnable;
  
  import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
  
  
  /**
   * A trace session context. Able to track and store trace sessions. A session is usually a user initiated query, and may
   * have multiple local and remote events before it is completed. All events and sessions are stored at keyspace.
   */
  class TracingImpl extends Tracing
  {
      public void stopSessionImpl()
      {
          final TraceStateImpl state = getStateImpl();
          if (state == null)
              return;
  
          int elapsed = state.elapsed();
          ByteBuffer sessionId = state.sessionIdBytes;
          int ttl = state.ttl;
  
          state.executeMutation(TraceKeyspace.makeStopSessionMutation(sessionId, elapsed, ttl));
      }
  
      public TraceState begin(final String request, final InetAddress client, final Map<String, String> parameters)
      {
          assert isTracing();
  
          final TraceStateImpl state = getStateImpl();
          assert state != null;
  
          final long startedAt = currentTimeMillis();
          final ByteBuffer sessionId = state.sessionIdBytes;
          final String command = state.traceType.toString();
          final int ttl = state.ttl;
  
          state.executeMutation(TraceKeyspace.makeStartSessionMutation(sessionId, client, parameters, request, startedAt, command, ttl));
          return state;
      }
  
      /**
       * Convert the abstract tracing state to its implementation.
       *
       * Expired states are not put in the sessions but the check is for extra safety.
       *
       * @return the state converted to its implementation, or null
       */
      private TraceStateImpl getStateImpl()
      {
          TraceState state = get();
          if (state == null)
              return null;
  
          if (state instanceof ExpiredTraceState)
          {
              ExpiredTraceState expiredTraceState = (ExpiredTraceState) state;
              state = expiredTraceState.getDelegate();
          }
  
          if (state instanceof TraceStateImpl)
          {
              return (TraceStateImpl)state;
          }
  
          assert false : "TracingImpl states should be of type TraceStateImpl";
          return null;
      }
  
      @Override
      protected TraceState newTraceState(InetAddressAndPort coordinator, TimeUUID sessionId, TraceType traceType)
      {
          return new TraceStateImpl(coordinator, sessionId, traceType);
      }
  
      /**
       * Called for non-local traces (traces that are not initiated by local node == coordinator).
       */
      public void trace(final ByteBuffer sessionId, final String message, final int ttl)
      {
          final String threadName = Thread.currentThread().getName();
  
          Stage.TRACING.execute(new WrappedRunnable()
          {
              public void runMayThrow()
              {
                  TraceStateImpl.mutateWithCatch(TraceKeyspace.makeEventMutation(sessionId, message, -1, threadName, ttl));
              }
          });
      }
  }
  