text:
package com.github.ambry.router;

import com.github.ambry.clustermap.ClusterMap;
import com.github.ambry.clustermap.ReplicaId;
import com.github.ambry.commons.BlobId;
import com.github.ambry.commons.BlobIdFactory;
import com.github.ambry.commons.ResponseHandler;
import com.github.ambry.commons.ServerErrorCode;
import com.github.ambry.config.RouterConfig;
import com.github.ambry.messageformat.BlobAll;
import com.github.ambry.messageformat.BlobData;
import com.github.ambry.messageformat.BlobInfo;
import com.github.ambry.messageformat.BlobType;
import com.github.ambry.messageformat.CompositeBlobInfo;
import com.github.ambry.messageformat.MessageFormatException;
import com.github.ambry.messageformat.MessageFormatFlags;
import com.github.ambry.messageformat.MessageFormatRecord;
import com.github.ambry.messageformat.MetadataContentSerDe;
import com.github.ambry.network.Port;
import com.github.ambry.network.RequestInfo;
import com.github.ambry.network.ResponseInfo;
import com.github.ambry.protocol.GetOption;
import com.github.ambry.protocol.GetRequest;
import com.github.ambry.protocol.GetResponse;
import com.github.ambry.protocol.RequestOrResponse;
import com.github.ambry.store.StoreKey;
import com.github.ambry.utils.Time;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * GetBlobOperation class is responsible for maintaining the state associated with a GetBlob operation, and completing
 * it. It would help to look at this class in conjunction with {@link PutOperation}.
 *
 * Blobs that need to be fetched are either simple (those that consist of only a single chunk) or composite (those
 * that consists of one metadata chunk and two or more data chunks). Whether a blob is simple or composite can only be
 * determined after the first chunk is fetched, based on whether the first chunk turns out to be a metadata chunk or
 * a data chunk.
 *
 * As soon as the first data chunk is fetched (which could be the first chunk in the case of simple blobs and the
 * second chunk fetched in the case of composite blobs), the operation callback is invoked (and the future is marked
 * as done) so that the caller can start reading in data. The rest of the chunks are asynchronously fetched and
 * buffered up to the maximum that can be buffered. When fetched chunks are consumed by the caller, subsequent chunks
 * become eligible to be fetched.
 */
class GetBlobOperation extends GetOperation {
  // the callback to use to complete the operation.
  private final RouterCallback routerCallback;
  // whether the operationCallback has been called already.
  private final AtomicBoolean operationCallbackInvoked = new AtomicBoolean(false);
  // The first chunk may be a metadata chunk if the blob is composite, or the only data chunk if the blob is simple.
  private final FirstGetChunk firstChunk;
  // Associated with all data chunks in the case of composite blobs. Only a fixed number of these are initialized.
  // Each of these is initialized with the information required to fetch a data chunk and is responsible for
  // retrieving and adding it to the list of chunk buffers. Once complete, they are reused to fetch subsequent data
  // chunks.
  private GetChunk[] dataChunks;
  // the factory to use to deserialize keys in a metadata chunk.
  private final BlobIdFactory blobIdFactory;
  // the total number of data chunks associated with this blob.
  private int numChunksTotal;
  // the total number of data chunks retrieved so far (and may or may not have been written out yet).
  private int numChunksRetrieved;
  // the maximum size of a data chunk in bytes
  private long chunkSize;
  // the total size of the object being fetched in this operation
  private long totalSize;
  // a byte range with defined start/end offsets that has been verified to be within the total blob size
  private ByteRange resolvedByteRange;
  // a list iterator to the chunk ids that need to be fetched for this operation, if this is a composite blob.
  private ListIterator<StoreKey> chunkIdIterator;
  // chunk index to retrieved chunk buffer mapping.
  private Map<Integer, ByteBuffer> chunkIndexToBuffer;
  // To find the GetChunk to hand over the response quickly.
  private final Map<Integer, GetChunk> correlationIdToGetChunk = new HashMap<>();
  // the blob info that is populated on OperationType.BlobInfo or OperationType.All
  private BlobInfo blobInfo;
  // the ReadableStreamChannel that is populated on OperationType.Blob or OperationType.All requests.
  private BlobDataReadableStreamChannel blobDataChannel;
  // the CompositeBlobInfo that will be set if (and when) this blob turns out to be a composite blob.
  private CompositeBlobInfo compositeBlobInfo;

  private static final Logger logger = LoggerFactory.getLogger(GetBlobOperation.class);

  /**
   * Construct a GetBlobOperation
   * @param routerConfig the {@link RouterConfig} containing the configs for get operations.
   * @param routerMetrics The {@link NonBlockingRouterMetrics} to be used for reporting metrics.
   * @param clusterMap the {@link ClusterMap} of the cluster
   * @param responseHandler the {@link ResponseHandler} responsible for failure detection.
   * @param blobIdStr the blob id associated with the operation in string form.
   * @param options the {@link GetBlobOptionsInternal} associated with the operation.
   * @param callback the callback that is to be called when the operation completes.
   * @param routerCallback the {@link RouterCallback} to use to complete operations.
   * @param blobIdFactory the factory to use to deserialize keys in a metadata chunk.
   * @param time the Time instance to use.
   * @throws RouterException if there is an error with any of the parameters, such as an invalid blob id.
   */
  GetBlobOperation(RouterConfig routerConfig, NonBlockingRouterMetrics routerMetrics, ClusterMap clusterMap,
      ResponseHandler responseHandler, String blobIdStr, GetBlobOptionsInternal options,
      Callback<GetBlobResultInternal> callback, RouterCallback routerCallback, BlobIdFactory blobIdFactory, Time time)
      throws RouterException {
    super(routerConfig, routerMetrics, clusterMap, responseHandler, blobIdStr, options, callback,
        routerMetrics.getBlobLocalColoLatencyMs, routerMetrics.getBlobCrossColoLatencyMs,
        routerMetrics.getBlobPastDueCount, time);
    this.routerCallback = routerCallback;
    this.blobIdFactory = blobIdFactory;
    firstChunk = new FirstGetChunk();
  }

  /**
   * {@inheritDoc}
   * <br>
   * If the callback for the operation was already called, then abort the reads from the channel and the caller
   * will be notified as part of the read callback eventually. If not, the notification will happen as part of the
   * operation completion callback.
   */
  @Override
  void abort(Exception abortCause) {
    if (operationCallbackInvoked.compareAndSet(false, true)) {
      NonBlockingRouter.completeOperation(null, getOperationCallback, null, abortCause);
    } else {
      setOperationException(abortCause);
      if (blobDataChannel != null && blobDataChannel.isReadCalled()) {
        blobDataChannel.completeRead();
      }
    }
    operationCompleted = true;
  }

  /**
   * Do all that needs to be done (cleanup, notification, etc.) on chunk completion and mark the state of the chunk
   * appropriately.
   * @param chunk the chunk that has completed.
   */
  private void onChunkOperationComplete(GetChunk chunk) {
    if (chunk.getChunkException() != null) {
      // if operation callback was already called, then this exception will have to be notified as part of the
      // read callback.
      setOperationException(chunk.getChunkException());
    }
    if (chunk == firstChunk) {
      if (operationCallbackInvoked.compareAndSet(false, true)) {
        Exception e = getOperationException();
        if (options.getChunkIdsOnly) {
          // If this is an operation just to get the chunk ids, then these ids will be returned as part of the
          // result callback and no more chunks will be fetched, so mark the operation as complete to let the
          // GetManager remove this operation.
          operationCompleted = true;
          List<StoreKey> chunkIds = e == null && compositeBlobInfo != null ? compositeBlobInfo.getKeys() : null;
          operationResult = new GetBlobResultInternal(null, chunkIds);
        } else {
          // Complete the operation from the caller's perspective, so that the caller can start reading from the
          // channel if there is no exception. The operation will not be marked as complete internally as subsequent
          // chunk retrievals and channel writes will need to happen and for that, this operation needs the GetManager to
          // poll it periodically. If any exception is encountered while processing subsequent chunks, those will be
          // notified during the channel read.
          long timeElapsed = time.milliseconds() - submissionTimeMs;
          routerMetrics.getBlobOperationLatencyMs.update(timeElapsed);
          if (e == null) {
            blobDataChannel = new BlobDataReadableStreamChannel();
            operationResult = new GetBlobResultInternal(new GetBlobResult(blobInfo, blobDataChannel), null);
          } else {
            blobDataChannel = null;
            operationResult = null;
            routerMetrics.onGetBlobError(e, options);
          }
        }
        NonBlockingRouter.completeOperation(null, getOperationCallback, operationResult, e);
      }
    }
    chunk.postCompletionCleanup();
    if (blobDataChannel != null) {
      blobDataChannel.maybeWriteToChannel();
    }
  }

  /**
   * Handle the given {@link ResponseInfo} by handing it over to the appropriate chunk that issued the request.
   * @param responseInfo the {@link ResponseInfo} to be handled.
   * @param getResponse the {@link GetResponse} associated with this response.
   */
  @Override
  void handleResponse(ResponseInfo responseInfo, GetResponse getResponse) {
    GetChunk getChunk = correlationIdToGetChunk.remove(
        ((RequestOrResponse) responseInfo.getRequestInfo().getRequest()).getCorrelationId());
    getChunk.handleResponse(responseInfo, getResponse);
    if (getChunk.isComplete()) {
      onChunkOperationComplete(getChunk);
    }
  }

  /**
   * As part of the poll, GetBlobOperation fetches new requests to be issued and updates the state based on
   * whether previously issued requests have timed out and so on. Additionally, any writes of previously retrieved
   * chunk buffers into the {@link AsyncWritableChannel} passed in by the caller also happens within this method.
   * @param requestRegistrationCallback the {@link RequestRegistrationCallback} to call for every request that gets
   *                                    created as part of this poll operation.
   */
  @Override
  void poll(RequestRegistrationCallback<GetOperation> requestRegistrationCallback) {
    if (operationCompleted) {
      return;
    }
    if (operationException.get() == null) {
      if (firstChunk.isReady() || firstChunk.isInProgress()) {
        firstChunk.poll(requestRegistrationCallback);
      }
      if (firstChunk.isComplete()) {
        // Although an attempt is made to write to the channel as soon as a chunk is successfully retrieved,
        // the caller might not have called readInto() and passed in a channel at the time. So an attempt is always
        // made from within poll.
        if (blobDataChannel != null) {
          blobDataChannel.maybeWriteToChannel();
        }
        // If this is a composite blob, poll for requests for subsequent chunks.
        if (dataChunks != null) {
          for (GetChunk dataChunk : dataChunks) {
            if (dataChunk.isFree() && chunkIdIterator.hasNext()) {
              dataChunk.initialize(chunkIdIterator.nextIndex(), (BlobId) chunkIdIterator.next());
            }
            if (dataChunk.isInProgress() || (dataChunk.isReady()
                && numChunksRetrieved - blobDataChannel.getNumChunksWrittenOut()
                < NonBlockingRouter.MAX_IN_MEM_CHUNKS)) {
              dataChunk.poll(requestRegistrationCallback);
              if (dataChunk.isComplete()) {
                onChunkOperationComplete(dataChunk);
                if (operationCompleted) {
                  break;
                }
              }
            }
          }
        }
      }
    }
    if (operationException.get() != null) {
      abort(operationException.get());
    }
  }

  // ReadableStreamChannel implementation:

  /**
   * A class that implements the result of this GetBlobOperation. This is instantiated if/when the first data chunk of
   * the blob arrives, when the operation callback is invoked.
   */
  private class BlobDataReadableStreamChannel implements ReadableStreamChannel {
    // whether this ReadableStreamChannel is open.
    private AtomicBoolean isOpen = new AtomicBoolean(true);
    // whether readInto() has been called yet by the caller on this ReadableStreamChannel.
    private volatile boolean readCalled = false;
    // The channel to write chunks of the blob into. This will be initialized when the caller calls the readInto().
    private AsyncWritableChannel asyncWritableChannel;
    // the callback to call when all the chunks are successfully written out into the asyncWritableChannel.
    private Callback<Long> readIntoCallback;
    // the future to mark as done when all the chunks are successfully written out into the asyncWritableChannel.
    private FutureResult<Long> readIntoFuture;
    // the number of bytes written out to the asyncWritableChannel. This would be the size of the blob eventually.
    private Long bytesWritten = 0L;
    // the number of chunks that have been written out to the asyncWritableChannel.
    private volatile int numChunksWrittenOut = 0;
    // the index of the next chunk that is to be written out to the asyncWritableChannel.
    private int indexOfNextChunkToWriteOut = 0;
    // whether this object has called the readIntoCallback yet.
    private final AtomicBoolean readIntoCallbackCalled = new AtomicBoolean(false);
    // the callback that is passed into the asyncWritableChannel write() operation.
    private final Callback<Long> chunkAsyncWriteCallback = new Callback<Long>() {
      @Override
      public void onCompletion(Long result, Exception exception) {
        bytesWritten += result;
        if (exception != null) {
          setOperationException(exception);
        }
        numChunksWrittenOut++;
        routerCallback.onPollReady();
      }
    };

    /**
     * The bytes that will be read from this channel is not known until the read is complete.
     * @return -1
     */
    @Override
    public long getSize() {
      return -1;
    }

    @Override
    public Future<Long> readInto(AsyncWritableChannel asyncWritableChannel, Callback<Long> callback) {
      if (!isOpen()) {
        throw new IllegalStateException("This ReadableStreamChannel has been closed");
      }
      if (readCalled) {
        throw new IllegalStateException("Cannot read the result of a GetBlob operation more than once");
      }
      this.asyncWritableChannel = asyncWritableChannel;
      readIntoCallback = callback;
      readIntoFuture = new FutureResult<>();
      readCalled = true;
      if (operationException.get() != null) {
        completeRead();
      }
      routerCallback.onPollReady();
      return readIntoFuture;
    }

    @Override
    public boolean isOpen() {
      return isOpen.get();
    }

    @Override
    public void close() throws IOException {
      if (isOpen.compareAndSet(true, false)) {
        if (numChunksWrittenOut != numChunksTotal) {
          setOperationException(new RouterException(
              "The ReadableStreamChannel for blob data has been closed by the user before all chunks were written out.",
              RouterErrorCode.ChannelClosed));
        }
      }
    }

    /**
     * @return whether readInto() has been called yet.
     */
    boolean isReadCalled() {
      return readCalled;
    }

    /**
     * @return the number of chunks that have been written out to the {@link AsyncWritableChannel}
     */
    int getNumChunksWrittenOut() {
      return numChunksWrittenOut;
    }

    /**
     * Attempt to write the data associated with the blob to the channel passed in by the caller (if the caller has
     * done so).
     */
    private void maybeWriteToChannel() {
      // if there are chunks available to be written out, do now.
      if (firstChunk.isComplete() && readCalled) {
        while (operationException.get() == null && chunkIndexToBuffer.containsKey(indexOfNextChunkToWriteOut)) {
          ByteBuffer chunkBuf = chunkIndexToBuffer.remove(indexOfNextChunkToWriteOut);
          asyncWritableChannel.write(chunkBuf, chunkAsyncWriteCallback);
          indexOfNextChunkToWriteOut++;
        }
        if (operationException.get() != null || numChunksWrittenOut == numChunksTotal) {
          completeRead();
        }
      }
    }

    /**
     * Complete the read from this {@link ReadableStreamChannel} by invoking the callback and marking the future.
     */
    void completeRead() {
      if (readIntoCallbackCalled.compareAndSet(false, true)) {
        Exception e = operationException.get();
        readIntoFuture.done(bytesWritten, e);
        if (readIntoCallback != null) {
          readIntoCallback.onCompletion(bytesWritten, e);
        }
        if (e == null) {
          updateChunkingAndSizeMetricsOnSuccessfulGet();
        } else {
          routerMetrics.onGetBlobError(e, options);
        }
        long totalTime = time.milliseconds() - submissionTimeMs;
        routerMetrics.getBlobOperationTotalTimeMs.update(totalTime);
      }
      operationCompleted = true;
    }

    /**
     * Update chunking and size related metrics - blob size, chunk count, and whether the blob is simple or composite.
     */
    private void updateChunkingAndSizeMetricsOnSuccessfulGet() {
      routerMetrics.getBlobSizeBytes.update(bytesWritten);
      routerMetrics.getBlobChunkCount.update(numChunksTotal);
      if (options != null && options.getBlobOptions.getRange() != null) {
        routerMetrics.getBlobWithRangeSizeBytes.update(bytesWritten);
        routerMetrics.getBlobWithRangeTotalBlobSizeBytes.update(totalSize);
      }
      if (numChunksTotal == 1) {
        routerMetrics.simpleBlobGetCount.inc();
      } else {
        routerMetrics.compositeBlobGetCount.inc();
      }
    }
  }

  /**
   * GetChunk is used to retrieve and hold a data chunk of a composite blob. An object of this class is initialized
   * to retrieve one data chunk at a time. Once the associated chunk is successfully retrieved, this object can be
   * reinitialized and used to retrieve a subsequent chunk.
   */
  private class GetChunk {
    // the operation tracker used to track the operation on the current chunk.
    private OperationTracker chunkOperationTracker;
    // the blob id of the current chunk.
    private BlobId chunkBlobId;
    // whether the operation on the current chunk has completed.
    private boolean chunkCompleted;
    // In general, when the operation tracker returns success, any previously saved exceptions are cleared. This flag
    // indicates that the set chunk exception should not be overwritten even when the operation tracker reports success.
    protected boolean retainChunkExceptionOnSuccess;
    // the index of the current chunk in the overall blob.
    protected int chunkIndex;
    // the most relevant exception encountered for the current chunk.
    protected RouterException chunkException;
    // For a GetChunk, responses may be handled multiple times. Regardless of the successTarget,
    // the actual body of the response is deserialized only once.
    protected boolean successfullyDeserialized;
    // map of correlation id to the request metadata for every request issued for this operation.
    protected final Map<Integer, GetRequestInfo> correlationIdToGetRequestInfo = new TreeMap<>();
    // the state of the chunk.
    protected volatile ChunkState state;

    /**
     * Construct a GetChunk
     * @param index the index (in the overall blob) of the initial data chunk that this GetChunk has to fetch.
     * @param id the {@link BlobId} of the initial data chunk that this GetChunk has to fetch.
     */
    GetChunk(int index, BlobId id) {
      reset();
      initialize(index, id);
    }

    /**
     * Do what needs to be done after the GetBlobOperation is done with the current chunk that has completed. When
     * this is called, the state of the chunk should be {@link ChunkState#Complete}
     */
    void postCompletionCleanup() {
      reset();
    }

    /**
     * @return the {@link GetOption} to associate with the {@link GetRequest}s that will be issued by this GetChunk.
     */
    GetOption getGetOption() {
      // Anything other than the first GetChunk should ignore Delete and Expired flags. This is to avoid errors due
      // to the blob getting expired or deleted in the middle of a retrieval - after the metadata chunk was
      // successfully retrieved.
      return GetOption.Include_All;
    }

    /**
     * Return the {@link MessageFormatFlags} to associate with a getBlob chunk operation.
     * @return {@link MessageFormatFlags#Blob}
     */
    MessageFormatFlags getOperationFlag() {
      return MessageFormatFlags.Blob;
    }

    /**
     * Reset the state of this GetChunk.
     */
    void reset() {
      chunkOperationTracker = null;
      chunkCompleted = false;
      retainChunkExceptionOnSuccess = false;
      chunkBlobId = null;
      chunkIndex = -1;
      chunkException = null;
      successfullyDeserialized = false;
      correlationIdToGetRequestInfo.clear();
      state = ChunkState.Free;
    }

    /**
     * Assign a chunk of the overall blob to this GetChunk.
     * @param index the index of the chunk of the overall blob that needs to be fetched through this GetChunk.
     * @param id the id of the chunk of the overall blob that needs to be fetched through this GetChunk.
     */
    void initialize(int index, BlobId id) {
      chunkIndex = index;
      chunkBlobId = id;
      chunkOperationTracker = getOperationTracker(chunkBlobId.getPartition());
      state = ChunkState.Ready;
    }

    /**
     * return the {@link RouterException} associated with the operation on this chunk, if any.
     * @return the {@link RouterException} associated with the operation on this chunk, if any.
     */
    RouterException getChunkException() {
      return chunkException;
    }

    /**
     * This is one of two main entry points to this class, the other being
     * {@link #handleResponse(ResponseInfo, GetResponse)}.
     * Apart from fetching requests to send out, this also checks for timeouts of issued requests,
     * status of the operation and anything else that needs to be done within this GetChunk. The callers guarantee
     * that this method is called on the GetChunks of an operation until either the operation, or the chunk operation
     * is completed.
     * @param requestRegistrationCallback the {@link RequestRegistrationCallback} to call for every request that gets
     *                                    created as part of this poll operation.
     */
    void poll(RequestRegistrationCallback<GetOperation> requestRegistrationCallback) {
      //First, check if any of the existing requests have timed out.
      cleanupExpiredInFlightRequests();
      checkAndMaybeComplete();
      if (!isComplete()) {
        fetchRequests(requestRegistrationCallback);
      }
    }

    /**
     * Clean up requests sent out by this operation that have now timed out.
     */
    private void cleanupExpiredInFlightRequests() {
      //First, check if any of the existing requests have timed out.
      Iterator<Map.Entry<Integer, GetRequestInfo>> inFlightRequestsIterator =
          correlationIdToGetRequestInfo.entrySet().iterator();
      while (inFlightRequestsIterator.hasNext()) {
        Map.Entry<Integer, GetRequestInfo> entry = inFlightRequestsIterator.next();
        if (time.milliseconds() - entry.getValue().startTimeMs > routerConfig.routerRequestTimeoutMs) {
          onErrorResponse(entry.getValue().replicaId);
          logger.trace("GetBlobRequest with correlationId {} in flight has expired for replica {} ", entry.getKey(),
              entry.getValue().replicaId.getDataNodeId());
          // Do not notify this as a failure to the response handler, as this timeout could simply be due to
          // connection unavailability. If there is indeed a network error, the NetworkClient will provide an error
          // response and the response handler will be notified accordingly.
          chunkException = new RouterException("Timed out waiting for a response", RouterErrorCode.OperationTimedOut);
          inFlightRequestsIterator.remove();
        } else {
          // the entries are ordered by correlation id and time. Break on the first request that has not timed out.
          break;
        }
      }
    }

    /**
     * Fetch {@link GetRequest}s to send for the current data chunk.
     */
    private void fetchRequests(RequestRegistrationCallback<GetOperation> requestRegistrationCallback) {
      Iterator<ReplicaId> replicaIterator = chunkOperationTracker.getReplicaIterator();
      while (replicaIterator.hasNext()) {
        ReplicaId replicaId = replicaIterator.next();
        replicaIterator.remove();
        String hostname = replicaId.getDataNodeId().getHostname();
        Port port = replicaId.getDataNodeId().getPortToConnectTo();
        GetRequest getRequest = createGetRequest(chunkBlobId, getOperationFlag(), getGetOption());
        RouterRequestInfo request = new RouterRequestInfo(hostname, port, getRequest, replicaId);
        int correlationId = getRequest.getCorrelationId();
        correlationIdToGetRequestInfo.put(correlationId, new GetRequestInfo(replicaId, time.milliseconds()));
        correlationIdToGetChunk.put(correlationId, this);
        requestRegistrationCallback.registerRequestToSend(GetBlobOperation.this, request);
        if (RouterUtils.isRemoteReplica(routerConfig, replicaId)) {
          logger.trace("Making request with correlationId {} to a remote replica {} in {} ", correlationId,
              replicaId.getDataNodeId(), replicaId.getDataNodeId().getDatacenterName());
          routerMetrics.crossColoRequestCount.inc();
        } else {
          logger.trace("Making request with correlationId {} to a local replica {}", correlationId,
              replicaId.getDataNodeId());
        }
        routerMetrics.getDataNodeBasedMetrics(replicaId.getDataNodeId()).getRequestRate.mark();
        state = ChunkState.InProgress;
      }
    }

    /**
     * Check if the operation on the chunk is eligible for completion, if so complete it.
     */
    void checkAndMaybeComplete() {
      if (chunkOperationTracker.isDone()) {
        if (!retainChunkExceptionOnSuccess && chunkOperationTracker.hasSucceeded()) {
          // override any previously set exceptions
          chunkException = null;
        }
        chunkCompleted = true;
      }
      if (chunkCompleted) {
        setOperationException(chunkException);
        state = ChunkState.Complete;
      }
    }

    /**
     * Handle the body of the response: Deserialize and add to the list of chunk buffers.
     * @param payload the body of the response.
     * @throws IOException if there is an IOException while deserializing the body.
     * @throws MessageFormatException if there is a MessageFormatException while deserializing the body.
     */
    void handleBody(InputStream payload) throws IOException, MessageFormatException {
      if (!successfullyDeserialized) {
        BlobData blobData = MessageFormatRecord.deserializeBlob(payload);
        chunkIndexToBuffer.put(chunkIndex, filterChunkToRange(blobData));
        numChunksRetrieved++;
        successfullyDeserialized = true;
      } else {
        // If successTarget > 1, then content reconciliation may have to be done. For now, ignore subsequent responses.
      }
    }

    /**
     * This method is the entry point for handling responses received for requests sent out on behalf of this chunk.
     * For gets, processing involves determining whether the request was successful, notifying the operation
     * tracker so it can track the status of the operation, and notifying the response handler for failure detection.
     * Finally, a check is done to determine whether the operation on the chunk is eligible for completion,
     * if so the chunk operation is completed right away.
     * @param responseInfo the response received for a request sent out on behalf of this chunk.
     * @param getResponse the {@link GetResponse} associated with this response.
     */
    void handleResponse(ResponseInfo responseInfo, GetResponse getResponse) {
      int correlationId = ((GetRequest) responseInfo.getRequestInfo().getRequest()).getCorrelationId();
      // Get the GetOperation that generated the request.
      GetRequestInfo getRequestInfo = correlationIdToGetRequestInfo.remove(correlationId);
      if (getRequestInfo == null) {
        // Ignore right away. This associated operation has completed.
        return;
      }
      long requestLatencyMs = time.milliseconds() - getRequestInfo.startTimeMs;
      routerMetrics.routerRequestLatencyMs.update(requestLatencyMs);
      routerMetrics.getDataNodeBasedMetrics(getRequestInfo.replicaId.getDataNodeId()).getRequestLatencyMs.update(
          requestLatencyMs);
      if (responseInfo.getError() != null) {
        logger.trace("GetBlobRequest with response correlationId {} timed out for replica {} ", correlationId,
            getRequestInfo.replicaId.getDataNodeId());
        chunkException = new RouterException("Operation timed out", RouterErrorCode.OperationTimedOut);
        onErrorResponse(getRequestInfo.replicaId);
      } else {
        if (getResponse == null) {
          logger.trace(
              "GetBlobRequest with response correlationId {} received an unexpected error on response deserialization from replica {} ",
              correlationId, getRequestInfo.replicaId.getDataNodeId());
          chunkException = new RouterException("Response deserialization received an unexpected error",
              RouterErrorCode.UnexpectedInternalError);
          onErrorResponse(getRequestInfo.replicaId);
        } else {
          if (getResponse.getCorrelationId() != correlationId) {
            // The NetworkClient associates a response with a request based on the fact that only one request is sent
            // out over a connection id, and the response received on a connection id must be for the latest request
            // sent over it. The check here ensures that is indeed the case. If not, log an error and fail this request.
            // There is no other way to handle it.
            logger.trace("GetBlobRequest with response correlationId {} mismatch from response {} for replica {} ",
                correlationId, getResponse.getCorrelationId(), getRequestInfo.replicaId.getDataNodeId());
            routerMetrics.unknownReplicaResponseError.inc();
            chunkException = new RouterException(
                "The correlation id in the GetResponse " + getResponse.getCorrelationId()
                    + " is not the same as the correlation id in the associated GetRequest: " + correlationId,
                RouterErrorCode.UnexpectedInternalError);
            onErrorResponse(getRequestInfo.replicaId);
            // we do not notify the ResponseHandler responsible for failure detection as this is an unexpected error.
          } else {
            try {
              processGetBlobResponse(getRequestInfo, getResponse);
            } catch (IOException | MessageFormatException e) {
              // This should really not happen. Again, we do not notify the ResponseHandler responsible for failure
              // detection.
              logger.trace(
                  "GetBlobRequest with response correlationId {} response deserialization failed for replica {} ",
                  correlationId, getRequestInfo.replicaId.getDataNodeId());
              routerMetrics.responseDeserializationErrorCount.inc();
              chunkException = new RouterException("Response deserialization received an unexpected error", e,
                  RouterErrorCode.UnexpectedInternalError);
              onErrorResponse(getRequestInfo.replicaId);
            }
          }
        }
      }
      checkAndMaybeComplete();
    }

    /**
     * Process the GetResponse extracted from a {@link ResponseInfo}
     * @param getRequestInfo the associated {@link RequestInfo} for which this response was received.
     * @param getResponse the {@link GetResponse} extracted from the {@link ResponseInfo}
     * @throws IOException if there is an error during deserialization of the GetResponse.
     * @throws MessageFormatException if there is an error during deserialization of the GetResponse.
     */
    private void processGetBlobResponse(GetRequestInfo getRequestInfo, GetResponse getResponse)
        throws IOException, MessageFormatException {
      ServerErrorCode getError = getResponse.getError();
      if (getError == ServerErrorCode.No_Error) {
        int partitionsInResponse = getResponse.getPartitionResponseInfoList().size();
        // Each get request issued by the router is for a single blob.
        if (partitionsInResponse != 1) {
          chunkException = new RouterException(
              "Unexpected number of partition responses, expected: 1, " + "received: " + partitionsInResponse,
              RouterErrorCode.UnexpectedInternalError);
        } else {
          getError = getResponse.getPartitionResponseInfoList().get(0).getErrorCode();
          if (getError == ServerErrorCode.No_Error) {
            handleBody(getResponse.getInputStream());
            chunkOperationTracker.onResponse(getRequestInfo.replicaId, true);
            if (RouterUtils.isRemoteReplica(routerConfig, getRequestInfo.replicaId)) {
              logger.trace("Cross colo request successful for remote replica in {} ",
                  getRequestInfo.replicaId.getDataNodeId().getDatacenterName());
              routerMetrics.crossColoSuccessCount.inc();
            }
          } else {
            // process and set the most relevant exception.
            processServerError(getError);
            if (getError == ServerErrorCode.Blob_Deleted || getError == ServerErrorCode.Blob_Expired) {
              // this is a successful response and one that completes the operation regardless of whether the
              // success target has been reached or not.
              chunkCompleted = true;
            } else {
              onErrorResponse(getRequestInfo.replicaId);
            }
          }
        }
      } else {
        logger.trace("Replica {} returned an error {} for a GetBlobRequest with response correlationId : {} ",
            getRequestInfo.replicaId.getDataNodeId(), getError, getResponse.getCorrelationId());
        onErrorResponse(getRequestInfo.replicaId);
      }
    }

    /**
     * Perform the necessary actions when a request to a replica fails.
     * @param replicaId the {@link ReplicaId} associated with the failed response.
     */
    void onErrorResponse(ReplicaId replicaId) {
      chunkOperationTracker.onResponse(replicaId, false);
      routerMetrics.routerRequestErrorCount.inc();
      routerMetrics.getDataNodeBasedMetrics(replicaId.getDataNodeId()).getRequestErrorCount.inc();
    }

    /**
     * Process the given {@link ServerErrorCode} and set operation status accordingly.
     * Receiving a {@link ServerErrorCode#Blob_Deleted}, {@link ServerErrorCode#Blob_Expired} or
     * {@link ServerErrorCode#Blob_Not_Found} is unexpected for all chunks except for the first.
     * @param errorCode the {@link ServerErrorCode} to process.
     */
    void processServerError(ServerErrorCode errorCode) {
      setChunkException(new RouterException("Server returned: " + errorCode, RouterErrorCode.UnexpectedInternalError));
    }

    /**
     * Set the exception associated with this chunk operation.
     * A {@link ServerErrorCode#Blob_Deleted} or {@link ServerErrorCode#Blob_Expired} error overrides any other
     * previously received exception.
     * @param exception the {@link RouterException} to possibly set.
     */
    void setChunkException(RouterException exception) {
      if (chunkException == null || exception.getErrorCode() == RouterErrorCode.BlobDeleted
          || exception.getErrorCode() == RouterErrorCode.BlobExpired) {
        chunkException = exception;
      }
    }

    /**
     * Slice this chunk's data to only include the bytes within the operation's specified byte range.
     * @param blobData the {@link BlobData} for this chunk.
     * @return A {@link ByteBuffer} that only includes bytes within the operation's specified byte range.
     */
    protected ByteBuffer filterChunkToRange(BlobData blobData) {
      ByteBuffer buf = blobData.getStream().getByteBuffer();
      if (options == null || options.getBlobOptions.getRange() == null) {
        return buf;
      }
      if (resolvedByteRange.getRangeSize() == 0) {
        buf.position(0);
        buf.limit(0);
      } else {
        long startOffsetInThisChunk = chunkIndex == 0 ? resolvedByteRange.getStartOffset() % chunkSize : 0;
        long endOffsetInThisChunk =
            chunkIndex == (numChunksTotal - 1) ? (resolvedByteRange.getEndOffset() % chunkSize) + 1 : chunkSize;
        buf.position((int) startOffsetInThisChunk);
        buf.limit((int) endOffsetInThisChunk);
      }
      return buf.slice();
    }

    /**
     * @return true if this GetChunk is free so a chunk of the overall blob can be assigned to it.
     */
    boolean isFree() {
      return state == ChunkState.Free;
    }

    /**
     * @return true if this GetChunk is assigned with a chunk of the overall blob and is ready to issue requests.
     */
    boolean isReady() {
      return state == ChunkState.Ready;
    }

    /**
     * @return true if the operation on this chunk is in progress.
     */
    boolean isInProgress() {
      return state == ChunkState.InProgress;
    }

    /**
     * @return true if the operation on the current chunk is complete.
     */
    boolean isComplete() {
      return state == ChunkState.Complete;
    }
  }

  /**
   * Special GetChunk used to retrieve and hold the first chunk of a blob. The first chunk is special because it
   * could either be a metadata chunk of a composite blob, or the single chunk of a simple blob,
   * and whether a chunk is composite or simple can only be determined after the first chunk is fetched.
   */
  private class FirstGetChunk extends GetChunk {

    /**
     * Construct a FirstGetChunk and initialize it with the {@link BlobId} of the overall operation.
     */
    FirstGetChunk() {
      super(-1, blobId);
    }

    /**
     * {@inheritDoc}
     * <br>
     * Post completion cleanup for the FirstGetChunk only involves clearing the correlation id map (so that
     * subsequent responses are ignored). The rest of the state of the FirstGetChunk is never cleared.
     */
    @Override
    void postCompletionCleanup() {
      correlationIdToGetRequestInfo.clear();
    }

    @Override
    GetOption getGetOption() {
      return options.getBlobOptions.getGetOption();
    }

    /**
     * Return the {@link MessageFormatFlags} to associate with the first getBlob chunk operation.
     * @return {@link MessageFormatFlags#Blob} for {@link GetBlobOptions.OperationType#Data}, or {@link MessageFormatFlags#All} by
     *         default.
     */
    @Override
    MessageFormatFlags getOperationFlag() {
      return options.getBlobOptions.getOperationType() == GetBlobOptions.OperationType.Data ? MessageFormatFlags.Blob
          : MessageFormatFlags.All;
    }

    /**
     * {@inheritDoc}
     * <br>
     * It would help to keep in mind while going through this method that the first chunk is either a metadata chunk
     * or the only chunk of the blob.
     */
    @Override
    void handleBody(InputStream payload) throws IOException, MessageFormatException {
      if (!successfullyDeserialized) {
        BlobData blobData;
        if (getOperationFlag() == MessageFormatFlags.Blob) {
          blobData = MessageFormatRecord.deserializeBlob(payload);
        } else {
          BlobAll blobAll = MessageFormatRecord.deserializeBlobAll(payload, blobIdFactory);
          blobInfo = blobAll.getBlobInfo();
          blobData = blobAll.getBlobData();
        }
        BlobType blobType = blobData.getBlobType();
        chunkIndexToBuffer = new TreeMap<>();
        if (blobType == BlobType.MetadataBlob) {
          handleMetadataBlob(blobData);
        } else {
          handleSimpleBlob(blobData);
        }
        successfullyDeserialized = true;
        state = ChunkState.Complete;
      } else {
        // Currently, regardless of the successTarget, only the first successful response is honored. Subsequent ones
        // are ignored. If ever in the future, we need some kind of reconciliation, this is the place
        // to do that. (Only after the reconciliation will the state be marked as complete).
      }
    }

    /**
     * {@inheritDoc}
     * <br>
     * Receiving a {@link ServerErrorCode#Blob_Deleted}, {@link ServerErrorCode#Blob_Expired} or
     * {@link ServerErrorCode#Blob_Not_Found} is not unexpected for the first chunk, unlike for subsequent chunks.
     */
    @Override
    void processServerError(ServerErrorCode errorCode) {
      logger.trace("Server returned an error: {} ", errorCode);
      switch (errorCode) {
        case Blob_Deleted:
          setChunkException(new RouterException("Server returned: " + errorCode, RouterErrorCode.BlobDeleted));
          break;
        case Blob_Expired:
          setChunkException(new RouterException("Server returned: " + errorCode, RouterErrorCode.BlobExpired));
          break;
        case Blob_Not_Found:
          setChunkException(new RouterException("Server returned: " + errorCode, RouterErrorCode.BlobDoesNotExist));
          break;
        default:
          setChunkException(
              new RouterException("Server returned: " + errorCode, RouterErrorCode.UnexpectedInternalError));
          break;
      }
    }

    /**
     * Process a metadata blob to find the data chunks that need to be fetched.
     * @param blobData the metadata blob's data.
     * @throws IOException
     * @throws MessageFormatException
     */
    private void handleMetadataBlob(BlobData blobData) throws IOException, MessageFormatException {
      ByteBuffer serializedMetadataContent = blobData.getStream().getByteBuffer();
      compositeBlobInfo =
          MetadataContentSerDe.deserializeMetadataContentRecord(serializedMetadataContent, blobIdFactory);
      chunkSize = compositeBlobInfo.getChunkSize();
      totalSize = compositeBlobInfo.getTotalSize();
      List<StoreKey> keys = compositeBlobInfo.getKeys();
      boolean rangeResolutionFailure = false;
      try {
        if (options != null && options.getBlobOptions.getRange() != null) {
          resolvedByteRange = options.getBlobOptions.getRange().toResolvedByteRange(totalSize);
          // Get only the chunks within the range.
          int firstChunkIndexInRange = (int) (resolvedByteRange.getStartOffset() / chunkSize);
          int lastChunkIndexInRange = (int) (resolvedByteRange.getEndOffset() / chunkSize);
          keys = keys.subList(firstChunkIndexInRange, lastChunkIndexInRange + 1);
        }
      } catch (IllegalArgumentException e) {
        onInvalidRange(e);
        rangeResolutionFailure = true;
      }
      if (!rangeResolutionFailure) {
        if (options.getChunkIdsOnly) {
          chunkIdIterator = null;
          numChunksTotal = 0;
          dataChunks = null;
        } else {
          chunkIdIterator = keys.listIterator();
          numChunksTotal = keys.size();
          dataChunks = new GetChunk[Math.min(keys.size(), NonBlockingRouter.MAX_IN_MEM_CHUNKS)];
          for (int i = 0; i < dataChunks.length; i++) {
            dataChunks[i] = new GetChunk(chunkIdIterator.nextIndex(), (BlobId) chunkIdIterator.next());
          }
        }
      }
    }

    /**
     * Process a simple blob and extract the requested data from the blob.
     * @param blobData the simple blob's data
     */
    private void handleSimpleBlob(BlobData blobData) {
      totalSize = blobData.getSize();
      chunkSize = totalSize;
      boolean rangeResolutionFailure = false;
      try {
        if (options != null && options.getBlobOptions.getRange() != null) {
          resolvedByteRange = options.getBlobOptions.getRange().toResolvedByteRange(totalSize);
        }
      } catch (IllegalArgumentException e) {
        onInvalidRange(e);
        rangeResolutionFailure = true;
      }
      if (!rangeResolutionFailure) {
        chunkIdIterator = null;
        dataChunks = null;
        chunkIndex = 0;
        numChunksTotal = 1;
        chunkIndexToBuffer.put(0, filterChunkToRange(blobData));
        numChunksRetrieved = 1;
      }
    }

    /**
     * On an invalid range, set a {@link RouterErrorCode#RangeNotSatisfiable} exception for this chunk, mark the chunk
     * as unconditionally completed, and set the chunk counters such that the operation will be completed.
     * @param exception the reason that the range was invalid.
     */
    private void onInvalidRange(Exception exception) {
      setChunkException(
          new RouterException("Range provided was not satisfiable.", exception, RouterErrorCode.RangeNotSatisfiable));
      retainChunkExceptionOnSuccess = true;
      chunkIdIterator = null;
      dataChunks = null;
      numChunksTotal = 0;
      numChunksRetrieved = 0;
    }
  }

  /**
   * Different states of a GetChunk.
   */
  enum ChunkState {
    /**
     * The GetChunk is free and can be assigned to hold a chunk of the overall blob.
     */
    Free,

    /**
     * The GetChunk has been assigned to get and hold a chunk of the overall blob.
     */
    Ready,

    /**
     * The GetChunk has issued requests and the operation on the chunk it holds is in progress.
     */
    InProgress,

    /**
     * The GetChunk is complete.
     */
    Complete,
  }
}


Find out why named driver exclusions, also called designated persons coverage exclusions, should or shouldn't be part of your car insurance policy.
For a number of years, the market for substandard auto policies has been a growing one. Initially, there were insurers that were not in the mainstream that.
Adding an additional named second driver, or multiple drivers, to your car insurance policy is a common requirement and one that it's essential to handle.
NEW YORK >> Drivers for car services and ride-hailing apps like Uber and Lyft are usually on their own when it comes to buying health insurance, but starting Sunday. corrected to show the Uber driv.
Named drivers are people you choose to drive your Motability car. Up to two drivers are included in your lease; these can be yourself, friends, family or carers.
His drivers are losing hundreds of dollars a day competing with these car services, but he says the competition. Lyft provided the following information about its safety policies and insurance: • L.
Jan 9, 2018. Fed up with paying through the nose for your car insurance? Adding a named driver to your policy can help to drive the cost of your cover down.
Feb 27, 2018. In most cases, car owners sign up for a car insurance plan so that they can avoid burning a hole in their pockets in case something goes wrong.
Named Driver Insurance. Car insurance can be expensive, and certain things like having had an accident in the past, having a prior motoring conviction, or even.
AIG Asia Pacific Insurance Pte.Ltd. REVISION IN NAMED DRIVER(S) – FOR NAMED DRIVERS POLICY. Insured's Name : Policy Number : Vehicle Number:.
Picture: AP Photo/Silvia Izquierdo Dr Cardoso said after abandoning her car he took an Uber to Sydney Airport to. while Ms.
If you drive someone else's vehicle then you will not be covered by their (the main driver) motor insurance policy – you must become a named driver on their.
Find out how a named driver car insurance policy can save you money! We present you with the very best deal possible by searching over 400 providers.
Car chase: Broward goes after Uber drivers – Since August, some 89 drivers in Broward have been cited for operating without the proper chauffer's license and permit showing the car has met county inspection and carries the required insurance, Fa.
Aug 28, 2017. While it is important to remember to add a named driver to your current car insurance policy, this is a routine procedure that need not be.
His theory is that someone from an oncoming car or someone standing on the side of the road shot into his vehicle as he was traveling along in the left lane of the roadway. While he believes the crime.
The suit named Green Line and the truck driver, Djafar Sharopov. Following additional negotiations with the company's insu.
Named Driver Car Insurance Rules at Compare the Market – What are the named driver car insurance rules? Make sure you stay within the law by reading our guide.
This means that you will become a named driver on that person's car insurance policy and you will be legally covered to drive their car. Another driver can also.
Uber's insurance also reached out to Collinson and said the damage of his vehicle would be covered, but he would be required to make a $1,000 deductible payment first. Collinson told me, given his car.
Hertz is also unwilling to provide information about its renter beyond his name, citing privacy laws. I've tried to claim this with our homeowners insurance. rental car or no. Here's problem No. 3:.
The car entered the east. as well as no vehicle liability insurance and failure to maintain control. * I understand and agree that registration on or use of this site constitutes agreement to its u.
Andrew Cuomo announced Wednesday that a committee would examine a device that would help police detect whether a driver involved in a car crash was texting. to the respective insurance company. Dis.
Drivers under. proposed law is named in memory of two teenage passengers killed in separate traffic crashes–Brady Grassinger of Los Angeles and Jared Cunningham of San Luis Obispo. Grassinger was.
Easily enforce open source policies in. saving billions in insurance money, and because of the possibility that self-drivi.
The scan raised questions about insurance coverage. It was his mother's car. We don. officer and every driver at every routine traffic stop. Local officials should launch a larger, comprehensive re.
Today's FAANGs can kill off "traditionals" anytime Insurance, banking, energy, telco, mobility, to name a few: What happens i.
Named drivers are people you choose to drive your Motability car. permitted drivers section of your Certificate of Motor Insurance are covered to drive your car.
A named driver is anyone who is named on your insurance policy, thereby meaning that you can let them drive your vehicle at any time as though it were their.
Do you know the difference between the named insured and a listed driver?. For younger drivers just starting out, trying to secure an auto insurance policy on.
Consumer demand has influenced corporate policies. to name one example, but that step may be more attainable after you've.


Over the past century, a community has developed around these mountain peaks, each over 4,000 feet in elevation.
My sons and I were on the trail that day because of a quest. This wasn't about exercise or stress relief or forest bathing. We were on a mission, to summit Wright and Algonquin. Two more peaks to add to our list.
The main trunkline out of Heart Lake, a north-south highway through the center of the High Peaks of the Adirondacks, is like Roman road: trod by so many booted feet that it is sunken, beaten into the earth, the banks of the trail often waist and shoulder high. It was a brilliant late summer day, and at the lower elevations the purple-tipped maples matched the purple granite of the mountains in a brief moment of cohesion. But as we climbed, the hardwoods retreated, and only the spruce and pine remained, until even they were driven out by the cold and the wind, leaving nothing but trampled rock and pockets of moss and wildflowers.
A few hikers passed us on the way up, including one woman in heavy-duty boots accompanied by her tongue-lolling dog and clearly miserable boyfriend. The happy calico mutt was wearing a harness covered in patches indicating peaks and their elevations.
"Well, she is a Forty-Sixer," the young woman said, as explanation.
"All of you are?" I asked; my sons and I want to be Forty-Sixers too.
And that made us feel good, because we were on number nine, and no longer noobs ourselves.
The Adirondacks in New York are the largest protected park in the continental United States—bigger than Yellowstone, Everglades, Glacier, and Grand Canyon combined—and within that boundary, 46 peaks rise over 4,000 feet of elevation. Anyone that climbs them all—in any order, over any number of years—becomes a Forty-Sixer. Among hikers in the know, it is a prestigious accomplishment, many marathons worth of trail-work. Some of the peaks lie within easy range of a parking lot, but most require multi-day excursions, to valley-floor base camps below each massif. That dog had done the work to earn those patches.
On that sunny day, my sons and I had chosen two of the more-accessible peaks. It was only three-and-a-half miles from our campsite up to the first summit, through forest that lay in a thick carpet. We were like mites passing among the bristles. But that relatively short path concealed 2,500 feet of elevation gain, and we were panting hard by the end. My youngest son, only eight years old, got vertigo near the end. We had left the trees behind, the trail became all bare rock marked by cairns, and while no steeper than earlier sections, the view was dizzying. For a while, my boy lay flat on his stomach so he couldn't fall off the mountain.
Wright Peak was worth all the effort, though. And so we added one more of the 46 to our list, our tenth. The rest of that list, in order of completion: Phelps, Porter, Cascade, Giant, Couchsachraga, Santanoni, Panther, Nye, Street. Only 36 more to go.
The Adirondack Mountains feel higher and more remote than they really are, lying only a few hours drive from the major East Coast metros, Montreal, and the upstate Rust Belt. This sense of isolation is partially a matter of climate, as it can snow on the summits even in summer. But it is also related to their natural history: the southernmost outpost of the Canadian Shield, a stand-alone dome scraped clean by the glaciers, exposing rock so ancient it predates multi-cellular life. On the flanks of the Adirondack peaks, the tiny stunted trees, brutalized all winter into the twisted husks of krummholz, can be hundreds of years old. And the lichen, sedge, and flowering grasses clinging to the exposed summits form a genuine alpine zone, remnants of the last ice age, a pin head's worth of Greenland transposed south and made accessible to average vacationers.
These natural resources have long attracted holiday-hikers and mountaineers alike. The Adirondacks are home to over 100,000 permanent residents, some living in ski towns and lumber hubs, and others in the poshest Gilded Age digs imaginable. They serve as an ex-urb for those fleeing other refuges closer to New York and Boston; when Concord and the Hudson Valley got too crowded, Emerson and the Vanderbilts moved north.
Bob and George Marshall were children of just such privilege, and in the 1910s and 1920s, summered at a Great Camp near the Saranac Lakes, in the heart of the park. With their guide and family friend Herb Clark, the brothers began hiking the high peaks when they were teenagers. By 1925, when Bob was 24 and George was just 21, the three men had already summited all 46 peaks believed to be over 4,000 feet, the treeline threshold for many of the mountains. Very few had established trails, though, and the matter might have remained there if Bob Marshall did not write a how-to guide, The High Peaks of the Adirondacks, in 1922.
Both Marshall brothers would go on to become environmental leaders. Bob founded the Wilderness Society. George served as president of that non-profit after his brother's death, and ran the Sierra Club for a while. But within the Adirondacks, the men's greatest contribution, arguably, is serving as the inspiration for hundreds of thousands of hikers that would attempt to trace their steps.
Among the first to catch the high-peak fever were the pastor and parishioners of Grace Methodist Church in Troy, near Albany, New York. Reverend Ernest Ryder was the seventh to summit the rotation, and would coin the term "Forty-Sixer." Ed Hudowalski made a hiking club out of his Sunday school class, and started leading trips. His wife Grace finished the circuit in 1937, the first woman and ninth overall to do so. As a courtesy, she began to record the names and dates of everyone who finished the 46, and when a new club, the Adirondack Forty-Sixers, held its first meeting near Heart Lake in the spring of 1948, they elected Grace the first President. She would also become the first historian, a job she did for 59 years.
The numbers are astounding in their growth. Most hikers take years to complete the 46. The current roster is 10,136, and while still exclusive, it is multiplying rapidly. In 2008, about 180 people were added to the rolls. The classes have increased every year since, to more than 700 in 2016. As many names have been added in the last 10 years as the first 72.
The Adirondacks are particularly photo-ready. They contain five essential elements for the perfect varied natural scene: water, rock, sky, vegetation, elevation. This is not just my opinion; check out #46er.
Among many outdoor enthusiasts, this whole process—seeking out summits only because they are on some arbitrary list, and then recording every hike—is sometimes derisively known as peak-bagging. Purists hold the exercise in poor regard for its emphasis on stamp-collecting and train-spotting, rather than the natural experience itself. The extreme version of peak-bagging involves racing the circuit, trying to beat the records for each FKT (fastest known time), a stat diligently tracked on an international message board.
Between 2000 and 2004, a man calling himself Cave Dog set a number of speed records, including the 46. Starting with the Colorado 14,000-footers—in jean shorts, no less—he also knocked off the New Hampshire 4,000-footers, the 35-over-3,500 in the Catskills, the 6,000-footers in Tennessee and North Carolina, and the Vermont Long Trail.
Cave Dog, also known (perhaps more appropriately) as Teddy Keizer, was from Oregon, and he beat the 46 record, long held by locals, by a full day. "Not everyone liked an outsider cruising through like that," say Jan Wellford, another speed hiker. Wellford was from southern Massachusetts, but had family in the Adirondacks' Keene Valley, and visited regularly. He decided to make a run at it, and reclaim the title for the locals.
Wellford set out on June 24, 2008. His wife drove him between trailheads, and he slept a few hours at a time, when his body gave out. He says the challenge is not the total distance, a relatively short 155 miles, but the elevation: over 60,000 feet. Wellford finished three days, 17 hours, and 14 minutes later. He beat Cave Dog by an hour.
Wellford now guides parties of inexperienced hikers to popular summits. He said he understands the purists, but disagrees with them. "If it takes a list to get people to come back to the mountains, I'm all for it," he says, adding that social media explains much of the recent popularity.
In the middle of his own FKT run, he took a selfie on the top of Wright, the handsome hulk of Algonquin in the background.
It turns out that the original geological survey of 1897, the one the Marshalls utilized in their hikes, wasn't quite right. Forty-Sixers still go by the traditional list, but modern methods have shown four of the 46 are actually below the threshold.
Most hikers today could do without those four: the shortest, only 3,820 feet, is Couchsachraga, an Algonquin word for "dismal wilderness." It lives up to the name because somehow, seemingly against the rules of hydrology that state water must drain away, a primordial swamp guards the summit.
But my kids and I have done Couchsachraga—miserable as it was, and no, I'm never going back—because we're completists and collectors and ultimately, agree with Wellford. If it takes a list and a goal to get father and sons out on the trail together for days at a time, then so be it.
On our latest hike, on that late-summer day, our goal, after Wright Peak, was Algonquin, a classic hike and, at 5,114 feet, the second highest of the 46. The whole path was visible from the summit of Wright: the drop into the thickly-forested saddle between the mountains, the steep climb out, the exposed slickrock that dotted the slope like islands in a green sea.
On our way off Wright, we detoured to a memorial that looks out over the valley. A small plaque was driven into the stone face, and along the ledge, the well-preserved crash remains of a B-47, the U.S. Air Force's first modern bomber. In 1962, an aircrew of four men was on a training mission out of Plattsburgh, a base on Lake Champlain 40 miles to the northeast. A storm rolled in unexpectedly, and high winds blew them off course. Unable to see, First Lieutenant Rodney D. Bloomgren, the aircraft's pilot, drove the plane directly into the broadside of the mountain. No one survived.
How many of the peak-baggers stop and notice this, I wondered? Only for a moment, though, because then we pushed on too.
Algonquin's approach proved more precarious than its final push to the summit. Hiking with children, I've learned chocolate cures all sorts of aches, pains, and bad attitudes, but it was hardly required as we scampered the cliff faces, some well-suited for a climbing gym. And then, all of sudden, we poked through the trees and stood in the alpine meadows of club moss and diapensia. The last half mile was joy. Number 11.
Standing at the top, next to the old rusting survey spike, was a young man with a long wizard beard, wispy like a frayed cloud. He introduced himself as the summit steward, and said it was his job to mind the top of Algonquin five days a week.
"Basically, I tell people to stay off the grass," he said.
"Too many. That's why most of these people are here," he said. Around us, young couples and middle-aged men in compression socks were busy on their smart phones, taking photos. We agreed it was a bit like Pokémon Go, trying to catch every high peak.


China: S Gansu, SE Qinghai, Sichuan, S and E Xizang [Tibet] where the population is very scattered in many areas.
Juniperus tibetica forms groves or small forests at high altitudes, often together with J. convallium. The altitudinal range is 2600–4780(–4900) metres above sea-level. These woods are often grazed by cattle (yaks) and degraded, being transformed into parkland with mats of Cyperaceae and low grasses and herbs, or further to Berberis-Juniperus scrub and Artemisia steppe. At lower altitudes it may occur in clearings of Picea forest, usually on south-facing slopes; at the tree limit, where it may be the only species, it returns to south-facing slopes indicating that temperature is the limiting factor. Locally it occurs in open stands of Cupressus torulosa var. gigantea. It occurs on rocky slopes and ridges, as well as old gravel terraces, on rocky soils from siliceous as well as calcareous parent material. The climate, mostly in the monsoon shadow of the main crest of the Himalayas, is continental with extremes of solar radiation and frost.
As the principal high altitude tree in large parts of Xizang [Tibet] and adjacent areas, this species is an important source of wood to local people, who use it for firewood and on a limited scale for other purposes, such as incense in Buddhist rituals. Increased population pressures in recent decades have resulted in shortages of a resource that renews itself only very slowly. It is rare in cultivation; seeds were collected by Joseph Rock in southern Gansu in 1926 (and distributed under the synonym J. distans); plants raised in the UK grew into a columnar habit with light green leaves.
This species is widespread but there is, however, considerable pressure from both direct uses by indigenous peoples (firewood in particular) as from grazing by domestic animals, which are likely to increase and have a detrimental effect on regeneration and possibly its long term survival in many areas (Miehe, pers. comm.).
Few trees are under protection where growing on sacred (Buddhist) sites. Field studies and community engagement projects have been undertaken with the help of researchers from the University of Marburg, Germany (Georg & Sabine Miehe) to assess the situation and try to find alternatives for destructive use of trees and habitat. Larger, and well managed/policed reserves, are urgently needed.
Farjon, A. (2013). Juniperus tibetica. In: IUCN 2013. IUCN Red List of Threatened Species. Version 2013.1. <www.iucnredlist.org>. Downloaded on 06 July 2013.
Miehe,G., & S. Miehe, J. Vogel, S.Co & and Duo L. (2007). Highest Treeline in the Northern Hemisphere Found in Southern Tibet. Mountain Research and Development. 27(2): 169-173.
A.Farjon, 2013. Juniperus tibetica, from the website, Threatened Conifers of The World (http://threatenedconifers.rbge.org.uk/taxa/details/950).


text:
Summary of the Federal Reserve March 2016 Meeting
GLD ETF Falls 2% Ahead of Fed Meeting
Google Inc (NASDAQ:GOOGL) Invests In Future
Is Nymox Pharmaceutical Corp. (NASDAQ:NYMX)Back in Action?
Sprint Corporation's (NYSE:S) Position in Regards to Other Mobile Carrier Giants
The Future of AbbVie's (NYSE:ABBV) Stock
Energy & Solar
About Stocks.org
Analysts & Contributors
You are at:Home»Category: "S&P 500" (Page 7)
Browsing: S&P 500
March 28, 2014 34 Top Gainers: Fuwei Films (Holdings) (NASDAQ:FFHL), Elephant Talk Communications (NYSEMKT:ETAK), China XD Plastics (NASDAQ:CXDC), Keryx Biopharmaceuticals (NASDAQ:KERX)
Fuwei Films (Holdings) Co., Ltd. (Nasdaq:FFHL) 19.5% HIGHER; announced that the Company has become aware that the fifth public auction…
March 26, 2014 48 Losers on Major News: JPMorgan Chase & Co. (NYSE:JPM), Microsoft Corporation (NASDAQ:MSFT), General Motors Company (NYSE:GM), Twitter Inc. (NYSE:TWTR)
JPMorgan Chase& Co. (NYSE:JPM) is losing another high-ranking executive, this time one who had been considered a possible successor to…
March 26, 2014 42 Gainers On major news: Apple Inc. (NASDAQ:AAPL), The Walt Disney Company (NYSE:DIS), International Business Machines Corp. (NYSE:IBM), Google Inc. (NASDAQ:GOOG)
Apple Inc. (NASDAQ:AAPL) won't have to pay damages to Samsung Electronics Co. and didn't infringe patents for certain products, a…
March 26, 2014 42 Overbought Stocks: Sonic Corporation, Dejour Energy Inc. (USA)
Sonic (NASDAQ:SONC) was having its best day in years Tuesday after the drive-in chain got past analysts' earnings targets and…
March 26, 2014 45 Active Stocks: Facebook Inc. (NASDAQ:FB), Yahoo! Inc. (NASDAQ:YHOO), Intel Corporation (NASDAQ:INTC), AT&T Inc. (NYSE:T)
Facebook Inc. (NASDAQ:FB) will acquire two-year-old Oculus VR Inc., a maker of virtual-reality glasses for gaming, for $2 billion, buying…
March 26, 2014 34 New Lows: Akebia Therapeutics Inc., GeoMet Inc, World Acceptance Corp. , VirnetX Holding Corporation
Akebia Therapeutics, Inc. (NASDAQ:AKBA) announced on 21 march Initial public offering of 5,882,353 shares of common stock was set at…
Previous 1 … 5 6 7
March 16, 2016 0 Summary of the Federal Reserve March 2016 Meeting
March 14, 2016 0 GLD ETF Falls 2% Ahead of Fed Meeting
April 24, 2015 0 Google Inc (NASDAQ:GOOGL) Invests In Future
April 4, 2015 0 Is Nymox Pharmaceutical Corp. (NASDAQ:NYMX)Back in Action?
July 3, 2014 20572 Facebook Inc (NASDAQ:FB) Acquires LiveRail, And It Could Mean More Accurately Target Ads
September 3, 2014 17274 MORGAN STANLEY (NYSE:MS): The Market can surge for the years to come, And the S&P 500 (INDEX:.INX) Might Go To 3,000
September 4, 2014 16870 Samsung Electronics Co Ltd (KRX:005930) set to reach the zenith with new gadgets
December 11, 2014 1839 Prospect Capital Corp. (NASDAQ:PSEC) Cuts Dividends
October 9, 2014 62 Apple Inc. (NASDAQ:AAPL) Responds to Icahn's Letter with Shares Buy Back Timeline and Promise for Review
September 3, 2014 71 Confusion and Anarchy In The S&P 500 (INDEXSP:.INX) – Stock in Focus Apple Inc (NASDAQ:AAPL), Morgan Stanley (NYSE:MS) and PepsiCo, Inc (NYSE:PEP)
August 19, 2014 60 Recuperation of S&P 500 after a strong disruption
September 3, 2014 167 MORGAN STANLEY (NYSE:MS): The Market can surge for the years to come, And the S&P 500 (INDEX:.INX) Might Go To 3,000

redpajama_set_name: RedPajamaCommonCrawl


text:
Q: TYPO3 loading default language instead of translation I'm using TYPO3 (with no other choice for the moment) and I have to add a secondary language to the website.
I have 2 languages:

*

*Default : English (en) set as L = 0

*English US (en_US) set as L = 1

I've made the change in the RealUrl and in the main template.

config.sys_language_uid = 0
config.language = en
config.locale_all = en_US.UTF-8
page.config.language = en

config.linkVars = L

[GLOBAL]

[globalVar = GP:L = 1]
  config {
    sys_language_uid = 1
    htmlTag_langKey  = en_US
    language = en_US
    locale_all = en_US.UTF-8
  }
[end]

[GLOBAL]

And

'preVars' => array(
      array(
                'GETvar' => 'no_cache',
                'valueMap' => array(
                    'no_cache' => 1,
                ),
                'noMatch' => 'bypass',
            ),
            array(
                'GETvar' => 'L',
                'valueMap' => array(
                    'en' => '0',
                    'en_US' => '1',
                ),
                'noMatch' => 'bypass',
                'valueDefault' => 'en',
            ),
    ),

So far, my language is created, both the original and the translation of my page appear on the Page Editing of TYPO3.
The URL works (www.mywebsite.com/en_US/mypage.html).
From this point it doesn't work anymore :
The page is generated, with the good URL, but loading the default language content.
(even with the preview test www.mywebsite.com/index.php?id=123&L=1 is not loading the good content)
Did I miss something ?

A: Resolved:
Forgot to precise the Original translation in the Page Edition
Select the original in the list (Transl.Orig) of the "General" tab of page editing.

redpajama_set_name: RedPajamaStackExchange


text:
6.Jun.2011 at 6 | Gavan Reilly
This week in Leinster House: June 7-9, 2011
We're told that there'll finally be some news on the committees front this week – at least, that's what the official sources have said – so we could be looking at a slightly more chocker schedule in the coming weeks. Until then, welcome to the first week of full sittings in both the Dáil and Seanad.
(Apologies for the absence of a post last week – your host was moving house and some things had to be allowed to slip!)
Both the Dáil and Seanad kick off at 2:30pm, with the Dáil beginning with Questions to the Taoiseach – and a batch of questions largely dominated by Gerry Adams who is tabling questions relating to the personal items of the court marshalled 1916 leaders and the handover of other Irish administrative documents from before partition. (The Seanad, meanwhile, will be going through its own Order of Business – which given some of the developments of the last week, most notably involving David Norris, should provide some theatre.)
Back downstairs, Questions to the Minister for Finance at 3:30pm will see Michael Noonan offer guidance on when Ireland expects to go back to the bond markets – and its progress on reducing that bailout interest rate – before Leaders' Questions at 4:15pm will see almost precisely the same points being raised in a far more theatrical manner. Thereafter the Dáil will pass a motion changing the rota of ministerial questions – finally getting rid of the sessions assigned to ministers who no longer exist – before discussing the Social Welfare and Pensions Bill. That bill, despite its relatively grand title, is more a housekeeping measure extending the provisions of earlier acts.
The Seanad, during this time, will be discussing the Fourth Report of the Special Rapporteur on Child Protection – which seems particularly timely, given the renewed furore over David Norris's 2002 Magill interview, but is portrayed in a far less timely manner when one realises the report was published in December. That'll take until 6pm, at which point matters on the adjournment wrap up the 24th Seanad's first Tuesday sitting.
Downstairs, the real politics begins at 7pm when Fianna Fáil uses its private members' time to table a Spent Convictions Bill. This bill, in essence, expunges a person's criminal record if their offences led to jail terms under a specific time, and if no other similar offences have been committed in the meantime. And why is this interesting? Because the Government has promised to publish 20 bills by the end of the summer session, and one of them is a Spent Convictions Bill. After the government voted down a Political Donations Bill and then introduced its own with less rigid provisions, opposing another opposition bill simply because it's an opposition bill may throw some cats among the pigeons. Adjournment matters at 8:30pm wrap up an interesting day.
The main – and more theatrical – weekly stint of Leaders' Questions kicks off Dáil business at 10:30am, followed by the Order of Business, more Questions to the Taoiseach (Alert! Micheál Martin wants to know whether Enda ran his College Green speech past Barack Obama!) and then more discussion on the Social Welfare and Pensions Bill.
The Seanad, meanwhile, kicks off at 10:30am with 75 minutes of Order of Business, before Statements on the Jobs Initiative bring the house to 1:30pm and lunch.
Downstairs, after lunch it's time for Questions to the Minister for Education and Skills, where Ruairí Quinn will no doubt face some criticism over his insistence to follow the path of Nick Clegg: promise no hike in college fees, and then be forced into doing it anyway. At least, that's what you'd think – but instead most of the questions on the agenda relate to personal cases, meaning the potential for sneaking in some jibes could be limited. Once that's done, it's back to the Social Welfare and Pensions Bill until 7pm.
The Seanad, during this time, will be holding a 150-minute debate on the Biological Weapons Bill 2010, a procedural piece making Ireland a party to a convention from 1972, before private members' time sees Fianna Fáil go on the offensive over water charges, and then adjournment matters at 7pm.
Fianna Fáil's private members' bill on spent convictions will keep things going in the Dáil before it, too, discusses matters on the adjournment at 8:30pm.
Eamon Gilmore stands in to take Order of Business at 10:30pm, before a quick motion on the Report on Services of the Defence Forces on UN Missions. Business then goes back to the Finance (No 2) Bill 2011 – the Bill giving legal effect to the Jobs Budget – with, potentially, some time left for the Welfare of Greyhounds Bill 2011, which proposes to regulate greyhound breeding establishments.
In the Seanad, meanwhile, the Order of Business will precede Statements on the 20 Year Strategy for the Irish Language which kicks off at 11:45am. At 2pm it's adjournment matters, before the part-timers clock off early.
Questions to the Minister for Jobs, Enterprise and Innovation at 3:30pm will be largely fragmented – with no overarching theme, and little common ground between the questions to Richard Bruton- before adjournment matters at 4:45pm wrap up the week.
As always, all of the week's business can be viewed on our live Dáil and live Seanad streams.
Tagged: Dáil Éireann, Seanad Éireann, This Week ,Enda Kenny, Michael Noonan, Richard Bruton, Ruairí Quinn
← This week in Leinster House: May 24-26, 2011 | Home | New Dáil Select committees announced →
You're currently reading "This week in Leinster House: June 7-9, 2011," an entry on agenda.ie by Gavan Reilly on Jun 06 2011 @ 9:12 pm


text:
Home › H. Jackson Brown, Jr. Quotes › Its Not Your Job To Get People To Like ...
"It's Not Your Job To Get People To Like You, It's Your Job To Like People."
— H. Jackson Brown, Jr. —
Antoine De Pluvinel
Eva Marcille
Joseph William Martin, Jr.
Vitali Klitschko
Waldemar Young
Willard Spiegelman
Windhy Puspitadewi
Quotes About Being Part Of Nature
"I love walking in the woods, on the trails, along the beaches. I love being part of nature. I love walking alone." — Grace Kelly
Opportunity To Serve Quotes
"We owe our troops the opportunity to serve in the best-planned, best-equipped, and best-led military force in the world, and we owe" — John F. Kerry
Metropolitan Funeral Quotes
"The Metropolitan Museum of Art some time ago held a display of contemporary art at which $52,000 was awarded to American sculptors, painters," — James Keller
Memories Never Fade Away Quotes
"What could he say about a future to those parents who couldnt let go of the past, who could do nothing but watch" — Jennifer Brown
Quotes About Court Jesters
"Oftentimes, actors are looked at as court jesters. They are not looked at as deep-thinking, smart people who do many other things" — Goldie Hawn
Cabral Quotes
"I grew up in the midst of poverty but every black kid that I knew could read and write. We have to talk" — bell hooks
Lost Outlaws Quotes
"The Hells Angels are very definitely a lower-class phenomenon, but their backgrounds are not necessarily poverty-stricken. Despite some grim moments, their parents seem" — Hunter S. Thompson
Battered Woman Quotes
"The battered woman for she wore a skirt with her right hand exposed, her left clutching at her side, stood singing of" — Virginia Woolf


text:
Lead Minister - joined the staff in 2007
After serving this congregation for seven years as the Associate Minister, the congregation called the Rev. Kathleen Owens as their Lead Minister in 2013. Kathleen continues to find and co-create a variety of ways for the congregation to create meaningful community, to nurture spiritual growth and act on our values to help heal our part of the world here in San Diego County. Kathleen feels especially blessed to share this ministry with the other gifted ministers and staff of this congregation, across its two campuses. Kathleen writes, "We at First UU Church are committed to offering bold and engaging worship and programs that stir the heart and mind, inviting people to explore more deeply how community, justice, care and joy can live more fully in our lives. We want to create more partnerships with local organizations in the work of justice so that the San Diego region can be more just, equitable and compassionate. We are committed to raising our collective and individual awareness in order to identify and remove cultural, physical and attitudinal barriers to full participation in our congregation and ensure a leadership development program for all ages. This is an exciting place to worship, learn, share and grow together in becoming our best and fullest selves so that we can use our gifts to bless the world. Wherever you are on your journey, if you come with an open heart and mind, you are welcome in this vibrant, diverse and multigenerational community." When Kathleen is not at church, she and her wife Jan are either walking and hiking in San Diego, traveling, enjoying movies and theatre or spending time with their family at home. As Lead Minister, Kathleen focuses on the following areas of ministry: Worship, Generosity, Pastoral Care, Children and Family Ministry, our South Bay campus and an emerging ministry to Military service members, their families and veterans. Kathleen holds a B.A. in English with a teaching certificate from Purdue University and a Masters of Divinity from Starr King School for the Ministry. For contact info, see our Ministers and Staff page.
Rev. Tania Márquez
Assistant Minister - joined the staff in 2017
"On Sundays, you are more likely to see me in our South Bay campus. I am South Bay´s part time minister and I am also in charge of our Caring Ministry, the People of Color group, coordinating our Wisdom Circles, and overseeing the Young Adult ministry at our church. I am also a program leader for the Unitarian Universalist College for Social Justice. I am excited about the work that a border church can engage in and happy to be a team member of First Church. I am inspired by the work of its members and the commitment to multicultural growth and social justice. It is an honor to serve this one as a minister". For contact info, see our Ministers and Staff page.
Matthew Waterman
Intern Minister - joined the staff in 2020
I am this year's Intern Minister for First UU Church of San Diego, albeit virtually, as I reside in the East Bay of the San Francisco area. After nearly a decade of working in banking, I transitioned into governmental accounting, where I worked for several more years. I found that I was still feeling a draw to go into ministry – one that I had been fighting since I was 12. I am still attending Starr King School for the Ministry, where I hope to graduate in May 2021. I also work for Starr King as the Director of Admissions and Recruitment. I am excited to be a part of this thriving and lively congregation and have been learning so much about congregational life. While I have ultimately not discerned where my path will lead me, I am drawn to congregational ministry or interim ministry. In my spare time, I love to spend time with family and friends, read, or visit the beach, especially Point Reyes North Beach. For contact info, see our Ministers and Staff page.
Rev. Jim Grant
Affiliate Minister - joined the staff in 2010
Rev. Jim Grant has been with First UU Church since 1996, having joined the church with his wife Betty in 1998. During this time Rev. Grant served as an Interim or Consulting minister in ten different UU Congregations and was away for the periods he served. Since retiring in 2010 he has been active without interruption with First UU. As Affiliate Minister he fills in on an "as needed" basis, primarily providing pastoral care and "rite of passage" services such as weddings and memorial (Celebration of Life) services, additionally teaching Adult Religious classes and workshops. For contact info, see our Ministers and Staff page.
Rev. Julie Forest
Affiliate Minister
I began my ministry on Bainbridge Island and have served churches in Washington, Wisconsin and most recently in the Rancho Mirage / Palm Springs area of the Southern California dessert. Ministry is my second career after being an on air radio programmer, DJ, and music director. I have been married to my wife since we got illegally married at First UU San Francisco. In addition, I am a mom of a young adult.
Although I retired at the General Assembly last year in Spokane Washington, I still maintain a private practice of spiritual direction as well as clergy coaching. I also do some community ministry for the LGBT center.
I am grateful to the board and the other ministers at First SD for welcoming me as an affiliate minister. I preach for this congregation occasionally and also do some teaching and some group facilitation. For contact info, see our Ministers and Staff page.
Rev. Katy Kroll Swanson, BCC
Affiliate Community Minister
I am an ordained Unitarian Universalist minister and I serve as a Hospital Chaplain at Rady Children's Hospital, San Diego. I was ordained in 2018 by the Unitarian Universalist Church of Long Beach, the church I grew up attending. I am Board Certified by the Association of Professional Chaplains.
At Rady Children's Hospital, I provide spiritual and emotional support to patients and families experiencing significant change and/or loss, and to the staff caring for them. I enjoy getting to know families from many different backgrounds, hearing their stories, and helping them make meaning from and find hope in challenging experiences. I feel especially called to walking with families in moments of crisis. I work with my colleagues to confront racial and economic healthcare inequity.
My husband, Steve, and I are members tof First UU Church and we have a young daughter. I have preached at our South Bay campus, sung in the JUUL Tones choir, and serve as a co-facilitator of the Caregivers & Allies Support Group at First UU.
I love working in healthcare, where I learn something new every day. I co-facilitate a Facebook group for UU Chaplain Colleagues which I worked to establish in 2017. It is an engaged, active group of approximately 80 UU chaplains working in healthcare and other community settings who support each other personally and professionally.
In my free time I enjoy swimming in the ocean or pool with my master's swim team, running, or taking my daughter to one of our local playgrounds. For contact info, see our Ministers and Staff page.
Rev. Bonnie Tarwater
Affiliate Community Minister - joined the staff in 2018
Rev. Bonnie Tarwater was ordained at First UU Church of SD in 1999, and is their first "affiliated community minister." She has served as a parish minister in both UU and UCC churches and currently serves, Church for Our Common Home, a church and counseling center, churchforourcommonhome.com a non-profit thatprovides artistic, religious and psychological services to awaken to the moral and ecologic crisis as an invitation for spiritual growth and creating loving community with all of creation, caring for our common home, Mother Earth. Bonnie is a Unitarian Christian dedicated to eco-feminism, the divine feminine, and AWE, Art, the Wisdom traditions and the Earth. Working previously in the professional theater she explores metaphor, symbol, color, dreams, visions, story, music, ritual, and dance for healing, community building and transformation. A devoted grandmother, she has a BA, from UCSD in Visual Art, an MFA, from ACT in theater, a CA Teaching Credential in Art and Theater from USIU, is certified from the Marin Institute of Projective Dream Work and received her M.Div. from Claremont School of Theology. She honors dreams as an ancient spiritual tradition whose time has come back and is the SD Rep for the International Association for the Study of Dreams for San Diego. For contact info, see our Ministers and Staff page.
Ministers Emeriti
Rev. Dr. Carolyn Sheet Owen-Towle
Carolyn Owen-Towle served as a UU Minster for many years. She is also a published author and popular speaker. As the daughter of renowned watercolorist Millard Sheets, Carolyn has always been immersed in the world of art and continues to be actively involved with many arts organizations. Carolyn served as co-minister of First UU Church of San Diego with her husband Tom from 1978 to 2002.
Rev. Tom Owen-Towle
With over four decades in Unitarian Universalist ministry and leadership in the men's movement, Tom Owen-Towle brings a seasoned perspective to the topics of progressive religion, partnership, gender justice, parenting, and citizenship in the global family. Tom Owen-Towle served as a parish minister since 1967 and is the author of two dozen books on various topics of personal growth, social compassion, and spiritual depth. He has been partnered in marriage for 40+ years to Carolyn Sheets Owen-Towle, and they are devoted parents of four and active grandparents of six. He is also a guitarist, a Little League coach, a budding magician and merry-maker, especially with seniors. Owen-Towle is a national leader who continues to conduct workshops and retreats on the core themes of his books. Tom served as co-minister of First UU Church of San Diego with his wife Carolyn from 1978 to 2002. For contact info, see our Ministers and Staff page.
Rose Reidel
rose@firstuusandiego.org


text:
<?php

/**
 * Generated data provider for mixed z unit test
 */
return function(\Faker\Generator $faker){
    return [
        'mixed z'   => [
            \Aedart\Model\Traits\Mixed\ZTrait::class,
            \Aedart\Model\Contracts\Mixed\ZAware::class,
            $faker->randomElement([$faker->word, $faker->uuid, $faker->randomNumber(), $faker->paragraphs()]),
            $faker->randomElement([$faker->word, $faker->uuid, $faker->randomNumber(), $faker->paragraphs()]),
        ]
    ];
};

redpajama_set_name: RedPajamaGithub


Congratulations on your beautiful art pieces! I'm sure you can't wait to get them up on your walls and start enjoying them right away. Before we hang them up, let's just quickly make sure you have the basics down for caring for them to keep them in mint condition!
Have you ever left a receipt or piece of paper on the dash board of your car for a few weeks or months? (Whoops, I know I have!) A couple months later that receipt is no longer legible. Now of course the inks used in professional print labs if of MUCH higher quality (and a completely different chemical makeup) than a cheap store receipt, but they can still be damaged by sunlight over time.
So, for a general rule #1: Don't hang or place your art pieces in direct sunlight!
When I was younger and I would get sick, my mom would use a humidifier to help my throat and lungs feel better. Problem was, the humidity in the room would cause my papers and photographs to warp. Moral of the story: water can be extremely damaging to photographs.
Rule #2 For any paper-based artwork, don't place them in humid areas like the bathroom or kitchen.
METAL: Handle your metal prints with care and protect the edges by not dropping it or placing it face down on a hard surface. Clean your metal artwork by gently wiping it using only a soft dry (or water dampened) cloth. These types of prints would do much better than paper products in humid environments, like the bathroom. I would not recommend using a photography spotlight to enhance the viewing of your metal print because it is so reflective that the light will bounce off make viewing very difficult. Make sure to handle it by the edges to avoid getting fingerprints on your freshly cleaned print! Refer to Rule #1 about hanging in direct sunlight!
Acrylic: Just like any other piece of fine art, try not to scratch or bang the corners of your acrylic print. Acrylic is very durable, but you can chip the edges if banged on a hard surface. You can use a standard glass cleaner, but I would recommend just using soap and water and a 100% cotton cloth to clean it. Make sure to handle it by the edges to avoid getting fingerprints on your freshly cleaned print! Refer to Rule #1 about hanging in direct sunlight!
Canvas: They type of archival quality canvas I print on is treated with a protective UV coating, making it resistant to fading over time. To keep it clean and dust-free, you can simply wipe with a damp cloth to maintain its brilliant appearance. Refer to Rule #1 about hanging in direct sunlight!
Paper: For floppy prints, Albums, Mounted Prints, and Folios, your main concern will be following Rules #1 and #2! Click HERE to learn more about care for paper-based photography products.
As always, I am here to answer any questions you might have! You can either comment below or email me by clicking HERE.


"eMpower" is one of our Web/Intranet based Time-Attendance & Leave Management software product which is designed and developed by our own in-house experienced and qualified software development team under the guidance of our management team. This is customizable, user friendly, proven stable and is compatible with any Time and Attendance/Access Control hardware's, can be integrated with SAP or ERP or any other customized application software's. This caters to all the requirements of a Small, Medium and Large scale Organizations / Institutions thereby delivering the desired results that will improve the decision making, streamlines the implementation and accelerates the return on Investment.
eMpower primarily works as a support system for Attendance Reader/Access Control System.
It has a utility to import swipe data from various Attendance Reader/Access Control Systems to its own database.
It processes the data and provides attendance/Leave/Out Duty and man hour details of all employees.