text:
title: "Subscribe to Messages from a Topic"
date: 2019-03-26T09:44:33-07:00
lastmod: 2019-07-29T12:00:00-07:00
weight: 2
toc: true
---

Subscribing to receive message from a topic with the Go CDK takes three steps:

1. [Open a subscription][] to a topic with the Pub/Sub service of your choice (once per
   subscription).
2. [Receive and acknowledge messages][] from the topic. After completing any
   work related to the message, use the Ack method to prevent it from being
   redelivered.

[Open a subscription]: {{< ref "#opening" >}}
[Receive and acknowledge messages]: {{< ref "#receiving" >}}

<!--more-->

## Opening a Subscription {#opening}

The first step in subscribing to receive messages from a topic is
to instantiate a portable [`*pubsub.Subscription`][] for your service.

The easiest way to do so is to use [`pubsub.OpenSubscription`][]
and a service-specific URL pointing to the topic, making sure you
["blank import"][] the driver package to link it in.

```go
import (
    "context"

    "gocloud.dev/pubsub"
    _ "gocloud.dev/pubsub/<driver>"
)
...
ctx := context.Background()
subs, err := pubsub.OpenSubscription(ctx, "<driver-url>")
if err != nil {
    return fmt.Errorf("could not open topic subscription: %v", err)
}
defer subs.Shutdown(ctx)
// subs is a *pubsub.Subscription; see usage below
...
```

See [Concepts: URLs][] for general background and the [guide below][]
for URL usage for each supported service.

Alternatively, if you need fine-grained
control over the connection settings, you can call the constructor function in
the driver package directly (like `gcppubsub.OpenSubscription`).

```go
import "gocloud.dev/pubsub/<driver>"
...
subs, err := <driver>.OpenSubscription(...)
...
```

You may find the [`wire` package][] useful for managing your initialization code
when switching between different backing services.

See the [guide below][] for constructor usage for each supported service.

[guide below]: {{< ref "#services" >}}
[`pubsub.OpenSubscription`]:
https://godoc.org/gocloud.dev/pubsub#OpenTopic
["blank import"]: https://golang.org/doc/effective_go.html#blank_import
[Concepts: URLs]: {{< ref "/concepts/urls.md" >}}
[`wire` package]: http://github.com/google/wire

## Receiving and Acknowledging Messages {#receiving}

A simple subscriber that operates on
[messages](https://godoc.org/gocloud.dev/pubsub#Message) serially looks like
this:

{{< goexample src="gocloud.dev/pubsub.ExampleSubscription_Receive" imports="0" >}}

If you want your subscriber to operate on incoming messages concurrently,
you can start multiple goroutines:

{{< goexample src="gocloud.dev/pubsub.ExampleSubscription_Receive_concurrent" imports="0" >}}

Note that the [semantics of message delivery][] can vary by backing service.

[`*pubsub.Subscription`]: https://godoc.org/gocloud.dev/pubsub#Subscription
[semantics of message delivery]: https://godoc.org/gocloud.dev/pubsub#hdr-At_most_once_and_At_least_once_Delivery

## Other Usage Samples

* [CLI Sample](https://github.com/google/go-cloud/tree/master/samples/gocdk-pubsub)
* [Order Processor sample](https://gocloud.dev/tutorials/order/)
* [pubsub package examples](https://godoc.org/gocloud.dev/pubsub#pkg-examples)

## Supported Pub/Sub Services {#services}

### Google Cloud Pub/Sub {#gcp}

The Go CDK can receive messages from a Google [Cloud Pub/Sub][] subscription.
The URLs use the project ID and the subscription ID.

[Cloud Pub/Sub]: https://cloud.google.com/pubsub/docs/

`pubsub.OpenSubscription` will use Application Default Credentials; if you have
authenticated via [`gcloud auth application-default login`][], it will use those credentials. See
[Application Default Credentials][GCP creds] to learn about authentication
alternatives, including using environment variables.

[GCP creds]: https://cloud.google.com/docs/authentication/production
[`gcloud auth application-default login`]: https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login

{{< goexample "gocloud.dev/pubsub/gcppubsub.Example_openSubscriptionFromURL" >}}

#### Google Cloud Pub/Sub Constructor {#gcp-ctor}

The [`gcppubsub.OpenSubscription`][] constructor opens a Cloud Pub/Sub
subscription. You must first obtain [GCP credentials][GCP creds] and then
create a gRPC connection to Cloud Pub/Sub. (This gRPC connection can be
reused among subscriptions.)

{{< goexample "gocloud.dev/pubsub/gcppubsub.ExampleOpenSubscription" >}}

[`gcppubsub.OpenSubscription`]: https://godoc.org/gocloud.dev/pubsub/gcppubsub#OpenSubscription

### Amazon Simple Queueing Service {#sqs}

The Go CDK can subscribe to an Amazon [Simple Queueing Service][SQS] (SQS)
topic. SQS URLs closely resemble the the queue URL, except the leading
`https://` is replaced with `awssqs://`. You should specify the `region`
query parameter to ensure your application connects to the correct region.

[SQS]: https://aws.amazon.com/sqs/

`pubsub.OpenSubscription` will create a default AWS Session with the
`SharedConfigEnable` option enabled; if you have authenticated with the AWS CLI,
it will use those credentials. See [AWS Session][] to learn about authentication
alternatives, including using environment variables.

[AWS Session]: https://docs.aws.amazon.com/sdk-for-go/api/aws/session/

{{< goexample "gocloud.dev/pubsub/awssnssqs.Example_openSubscriptionFromURL" >}}

If your messages are being sent to SQS directly, or if they are being delivered
via an SNS topic with `RawMessageDelivery` enabled, set a `raw=true` query
parameter in your URL, or set `SubscriberOptions.Raw` to `true` if you're using
the constructors. By default, the subscription will use heuristics to identify
whether the message bodies are raw or [SNS JSON][].

Messages with a `base64encoded` message attribute will be automatically
[Base64][] decoded before being returned. See the [SNS publishing guide][]
or the [SQS publishing guide][] for more details.

[Base64]: https://en.wikipedia.org/wiki/Base64
[SNS publishing guide]: {{< ref "./publish.md#sns" >}}
[SQS publishing guide]: {{< ref "./publish.md#sqs" >}}
[SNS JSON]: https://aws.amazon.com/sns/faqs/#Raw_message_delivery

#### Amazon SQS Constructor {#sqs-ctor}

The [`awssnssqs.OpenSubscription`][] constructor opens an SQS queue. You must
first create an [AWS session][] with the same region as your topic:

{{< goexample "gocloud.dev/pubsub/awssnssqs.ExampleOpenSubscription" >}}

[`awssnssqs.OpenSubscription`]: https://godoc.org/gocloud.dev/pubsub/awssnssqs#OpenSubscription
[AWS session]: https://docs.aws.amazon.com/sdk-for-go/api/aws/session/

### Azure Service Bus {#azure}

The Go CDK can recieve messages from an [Azure Service Bus][] subscription.
The URL for subscribing is the topic name with the
subscription name in the `subscription` query parameter.
`pubsub.OpenSubscription` will use the environment variable
`SERVICEBUS_CONNECTION_STRING` to obtain the Service Bus Connection String
you need to copy [from the Azure portal][Azure connection string].

{{< goexample "gocloud.dev/pubsub/azuresb.Example_openSubscriptionFromURL" >}}

[AMQP 1.0]: https://www.amqp.org/
[Azure connection string]: https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions#get-the-connection-string
[Azure Service Bus]: https://azure.microsoft.com/en-us/services/service-bus/

#### Azure Service Bus Constructor {#azure-ctor}

The [`azuresb.OpenSubscription`][] constructor opens an Azure Service Bus
subscription. You must first connect to the topic and subscription using the
[Azure Service Bus library][] and then pass the subscription to
`azuresb.OpenSubscription`. There are also helper functions in the `azuresb`
package to make this easier.

{{< goexample "gocloud.dev/pubsub/azuresb.ExampleOpenSubscription" >}}

[`azuresb.OpenSubscription`]: https://godoc.org/gocloud.dev/pubsub/azuresb#OpenSubscription
[Azure Service Bus library]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus

### RabbitMQ {#rabbitmq}

The Go CDK can receive messages from an [AMQP 0.9.1][] queue, the dialect of
AMQP spoken by [RabbitMQ][]. A RabbitMQ URL only includes the queue name.
The RabbitMQ's server is discovered from the `RABBIT_SERVER_URL` environment
variable (which is something like `amqp://guest:guest@localhost:5672/`).

{{< goexample "gocloud.dev/pubsub/rabbitpubsub.Example_openSubscriptionFromURL" >}}

[AMQP 0.9.1]: https://www.rabbitmq.com/protocol.html
[RabbitMQ]: https://www.rabbitmq.com

#### RabbitMQ Constructor {#rabbitmq-ctor}

The [`rabbitpubsub.OpenSubscription`][] constructor opens a RabbitMQ queue.
You must first create an [`*amqp.Connection`][] to your RabbitMQ instance.

{{< goexample "gocloud.dev/pubsub/rabbitpubsub.ExampleOpenSubscription" >}}

[`*amqp.Connection`]: https://pkg.go.dev/github.com/rabbitmq/amqp091-go#Connection
[`rabbitpubsub.OpenSubscription`]: https://godoc.org/gocloud.dev/pubsub/rabbitpubsub#OpenSubscription

### NATS {#nats}

The Go CDK can publish to a [NATS][] subject. A NATS URL only includes the
subject name. The NATS server is discovered from the `NATS_SERVER_URL`
environment variable (which is something like `nats://nats.example.com`).

{{< goexample "gocloud.dev/pubsub/natspubsub.Example_openSubscriptionFromURL" >}}

NATS guarantees at-most-once delivery; it will never redeliver a message.
Therefore, `Message.Ack` is a no-op.

To parse messages [published via the Go CDK][publish#nats], the NATS driver
will first attempt to decode the payload using [gob][]. Failing that, it will
return the message payload as the `Data` with no metadata to accomodate
subscribing to messages coming from a source not using the Go CDK.

[gob]: https://golang.org/pkg/encoding/gob/
[NATS]: https://nats.io/
[publish#nats]: {{< ref "./publish.md#nats" >}}

#### NATS Constructor {#nats-ctor}

The [`natspubsub.OpenSubscription`][] constructor opens a NATS subject as a
topic. You must first create an [`*nats.Conn`][] to your NATS instance.

{{< goexample "gocloud.dev/pubsub/natspubsub.ExampleOpenSubscription" >}}

[`*nats.Conn`]: https://godoc.org/github.com/nats-io/go-nats#Conn
[`natspubsub.OpenSubscription`]: https://godoc.org/gocloud.dev/pubsub/natspubsub#OpenSubscription

### Kafka {#kafka}

The Go CDK can receive messages from a [Kafka][] cluster.
A Kafka URL includes the consumer group name, plus at least one instance
of a query parameter specifying the topic to subscribe to.
The brokers in the Kafka cluster are discovered from the
`KAFKA_BROKERS` environment variable (which is a comma-delimited list of
hosts, something like `1.2.3.4:9092,5.6.7.8:9092`).

{{< goexample "gocloud.dev/pubsub/kafkapubsub.Example_openSubscriptionFromURL" >}}

[Kafka]: https://kafka.apache.org/

#### Kafka Constructor {#kafka-ctor}

The [`kafkapubsub.OpenSubscription`][] constructor creates a consumer in a
consumer group, subscribed to one or more topics.

In addition to the list of brokers, you'll need a [`*sarama.Config`][], which
exposes many knobs that can affect performance and semantics; review and set
them carefully. [`kafkapubsub.MinimalConfig`][] provides a minimal config to
get you started.

{{< goexample "gocloud.dev/pubsub/kafkapubsub.ExampleOpenSubscription" >}}

[`*sarama.Config`]: https://godoc.org/github.com/Shopify/sarama#Config
[`kafkapubsub.OpenSubscription`]: https://godoc.org/gocloud.dev/pubsub/kafkapubsub#OpenSubscription
[`kafkapubsub.MinimalConfig`]: https://godoc.org/gocloud.dev/pubsub/kafkapubsub#MinimalConfig

### In-Memory {#mem}

The Go CDK includes an in-memory Pub/Sub provider useful for local testing.
The names in `mem://` URLs are a process-wide namespace, so subscriptions to
the same name will receive messages posted to that topic. For instance, if
you open a topic `mem://topicA` and open two subscriptions with
`mem://topicA`, you will have two subscriptions to the same topic.

{{< goexample "gocloud.dev/pubsub/mempubsub.Example_openSubscriptionFromURL" >}}

#### In-Memory Constructor {#mem-ctor}

To create a subscription to an in-memory Pub/Sub topic, pass the [topic you
created][publish-mem-ctor] into the [`mempubsub.NewSubscription` function][].
You will also need to pass an acknowledgement deadline: once a message is
received, if it is not acknowledged after the deadline elapses, then it will be
redelivered.

{{< goexample "gocloud.dev/pubsub/mempubsub.ExampleNewSubscription" >}}

[`mempubsub.NewSubscription` function]: https://godoc.org/gocloud.dev/pubsub/mempubsub#NewSubscription
[publish-mem-ctor]: {{< ref "./publish.md#mem-ctor" >}}


text:
module Google
  module Cloud
    module Domains
      module V1
        VERSION = "0.2.0"
      end
    end
  end
end

redpajama_set_name: RedPajamaGithub


text:
package za.co.cporm.provider;

import android.annotation.TargetApi;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Build;
import android.os.CancellationSignal;
import android.support.annotation.NonNull;
import android.text.TextUtils;

import za.co.cporm.model.CPOrm;
import za.co.cporm.model.CPOrmConfiguration;
import za.co.cporm.model.CPOrmDatabase;
import za.co.cporm.model.generate.TableDetails;
import za.co.cporm.model.util.ManifestHelper;
import za.co.cporm.provider.util.UriMatcherHelper;
import za.co.cporm.util.CPOrmLog;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * The base content provided that will expose all of the model objects.
 * Objects are expose in the form of authority/table_name/*
 */
public class CPOrmContentProvider extends ContentProvider {

    public static final String PARAMETER_OFFSET = "OFFSET";
    public static final String PARAMETER_LIMIT = "LIMIT";
    public static final String PARAMETER_SYNC = "IS_SYNC";
    public static final String PARAMETER_CHANGE_TYPE = "CPORM_CHANGE_TYPE";
    public static final String PARAMETER_NOTIFY_CHANGES = "NOTIFY_CHANGES";

    private final ThreadLocal<Boolean> isBatchOperation = new ThreadLocal<>();
    private final ThreadLocal<Set<Uri>> changedUri = new ThreadLocal<>();

    protected CPOrmConfiguration cPOrmConfiguration;
    protected CPOrmDatabase database;
    protected UriMatcherHelper uriMatcherHelper;
    protected boolean debugEnabled;

    @Override
    public boolean onCreate() {

        cPOrmConfiguration = ManifestHelper.getConfiguration(getContext());
        database = new CPOrmDatabase(getContext(), cPOrmConfiguration);

        debugEnabled = cPOrmConfiguration.isQueryLoggingEnabled();
        return true;
    }

    @Override
    public void attachInfo(Context context, ProviderInfo info) {
        super.attachInfo(context, info);

        uriMatcherHelper = new UriMatcherHelper(getContext(), info.authority);
        uriMatcherHelper.init(getContext(), database.getcPOrmConfiguration(), database.getTableDetailsCache());
    }

    @Override
    public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        TableDetails tableDetails = uriMatcherHelper.getTableDetails(uri);
        SQLiteDatabase db = database.getReadableDatabase();
        String limit = constructLimit(uri);
        Boolean distinct = uri.getBooleanQueryParameter("DISTINCT", false);
        String groupBy = uri.getQueryParameter("GROUP_BY");
        String having = uri.getQueryParameter("HAVING");

        if (debugEnabled) {
            CPOrmLog.d("********* Query **********");
            CPOrmLog.d("Uri: " + uri);
            CPOrmLog.d("Projection: " + Arrays.toString(projection));
            CPOrmLog.d("Selection: " + selection);
            CPOrmLog.d("Args: " + Arrays.toString(selectionArgs));
            CPOrmLog.d("Sort: " + sortOrder);
            CPOrmLog.d("Limit: " + limit);
            CPOrmLog.d("Distinct: " + distinct);
            CPOrmLog.d("Group By: " + groupBy);
            CPOrmLog.d("Having: " + having);
        }

        Cursor cursor;

        if (uriMatcherHelper.isSingleItemRequested(uri)) {

            String itemId = uri.getLastPathSegment();
            cursor = db.query(true, tableDetails.getTableName(), projection, tableDetails.getPrimaryKeyClause(), new String[]{itemId}, null, null, null, "1");
        } else
            cursor = db.query(distinct, tableDetails.getTableName(), projection, selection, selectionArgs, groupBy, having, sortOrder, limit);

        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) {

        TableDetails tableDetails = uriMatcherHelper.getTableDetails(uri);
        SQLiteDatabase db = database.getReadableDatabase();
        String limit = constructLimit(uri);
        Boolean distinct = uri.getBooleanQueryParameter("DISTINCT", false);
        String groupBy = uri.getQueryParameter("GROUP_BY");
        String having = uri.getQueryParameter("HAVING");

        if (debugEnabled) {
            CPOrmLog.d("********* Query **********");
            CPOrmLog.d("Uri: " + uri);
            CPOrmLog.d("Projection: " + Arrays.toString(projection));
            CPOrmLog.d("Selection: " + selection);
            CPOrmLog.d("Args: " + Arrays.toString(selectionArgs));
            CPOrmLog.d("Sort: " + sortOrder);
            CPOrmLog.d("Limit: " + limit);
            CPOrmLog.d("Distinct: " + distinct);
            CPOrmLog.d("Group By: " + groupBy);
            CPOrmLog.d("Having: " + having);
        }

        Cursor cursor;

        if (uriMatcherHelper.isSingleItemRequested(uri)) {

            String itemId = uri.getLastPathSegment();
            cursor = db.query(true, tableDetails.getTableName(), projection, tableDetails.getPrimaryKeyClause(), new String[]{itemId}, null, null, null, "1", cancellationSignal);
        } else
            cursor = db.query(distinct, tableDetails.getTableName(), projection, selection, selectionArgs, groupBy, having, sortOrder, limit, cancellationSignal);

        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }

    @Override
    public String getType(@NonNull Uri uri) {

        return uriMatcherHelper.getType(uri);
    }

    @Override
    public Uri insert(@NonNull Uri uri, ContentValues contentValues) {

        TableDetails tableDetails = uriMatcherHelper.getTableDetails(uri);
        SQLiteDatabase db = database.getWritableDatabase();

        if (debugEnabled) {
            CPOrmLog.d("********* Insert **********");
            CPOrmLog.d("Uri: " + uri);
            CPOrmLog.d("Content Values: " + contentValues);
        }

        long insertId = db.insertOrThrow(tableDetails.getTableName(), null, contentValues);

        if (insertId == -1)
            throw new IllegalArgumentException("Failed to insert row for into table " + tableDetails.getTableName() + " using values " + contentValues);

        Uri insertedUri;
        TableDetails.ColumnDetails primaryKeyColumn = tableDetails.findPrimaryKeyColumn();
        if (primaryKeyColumn.isAutoIncrement()) {
            insertedUri = uriMatcherHelper.generateSingleItemUri(tableDetails, insertId)
                    .buildUpon()
                    .appendQueryParameter(PARAMETER_CHANGE_TYPE, CPOrm.ChangeType.INSERT.toString())
                    .build();
        } else {

            String primaryKeyValue = contentValues.getAsString(primaryKeyColumn.getColumnName());
            insertedUri = uriMatcherHelper.generateSingleItemUri(tableDetails, primaryKeyValue)
                    .buildUpon()
                    .appendQueryParameter(PARAMETER_CHANGE_TYPE, CPOrm.ChangeType.INSERT.toString())
                    .build();
        }

        if(!isBatchOperation()) notifyChanges(insertedUri, tableDetails);
        else changedUri.get().add(insertedUri);

        return insertedUri;
    }

    @Override
    public int delete(@NonNull Uri uri, String where, String[] args) {

        TableDetails tableDetails = uriMatcherHelper.getTableDetails(uri);
        SQLiteDatabase db = database.getWritableDatabase();

        if (debugEnabled) {
            CPOrmLog.d("********* Delete **********");
            CPOrmLog.d("Uri: " + uri);
            CPOrmLog.d("Where: " + where);
            CPOrmLog.d("Args: " + Arrays.toString(args));
        }

        int deleteCount;

        if (uriMatcherHelper.isSingleItemRequested(uri)) {

            String itemId = uri.getLastPathSegment();
            TableDetails.ColumnDetails primaryKeyColumn = tableDetails.findPrimaryKeyColumn();
            deleteCount = db.delete(tableDetails.getTableName(), primaryKeyColumn.getColumnName() + " = ?", new String[]{itemId});
        } else deleteCount = db.delete(tableDetails.getTableName(), where, args);

        if (deleteCount == 0)
            return deleteCount;

        Uri deleteUri = uri.buildUpon().appendQueryParameter(PARAMETER_CHANGE_TYPE, CPOrm.ChangeType.DELETE.toString()).build();
        if(!isBatchOperation()) notifyChanges(deleteUri, tableDetails);
        else changedUri.get().add(deleteUri);

        return deleteCount;
    }

    @Override
    public int update(@NonNull Uri uri, ContentValues contentValues, String where, String[] args) {

        TableDetails tableDetails = uriMatcherHelper.getTableDetails(uri);
        SQLiteDatabase db = database.getWritableDatabase();

        if (debugEnabled) {
            CPOrmLog.d("********* Update **********");
            CPOrmLog.d("Uri: " + uri);
            CPOrmLog.d("Content Values: " + contentValues);
            CPOrmLog.d("Where: " + where);
            CPOrmLog.d("Args: " + Arrays.toString(args));
        }

        int updateCount;

        if (uriMatcherHelper.isSingleItemRequested(uri)) {

            String itemId = uri.getLastPathSegment();
            TableDetails.ColumnDetails primaryKeyColumn = tableDetails.findPrimaryKeyColumn();
            updateCount = db.update(tableDetails.getTableName(), contentValues, primaryKeyColumn.getColumnName() + " = ?", new String[]{itemId});
        } else updateCount = db.update(tableDetails.getTableName(), contentValues, where, args);

        if (updateCount > 0 && shouldChangesBeNotified(tableDetails, contentValues)) {
            Uri updateUri = uri.buildUpon().appendQueryParameter(PARAMETER_CHANGE_TYPE, CPOrm.ChangeType.UPDATE.toString()).build();
            if(!isBatchOperation()) notifyChanges(updateUri, tableDetails);
            else changedUri.get().add(updateUri);
        }

        return updateCount;
    }

    @Override
    public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {

        int length = values.length;
        if (length == 0)
            return 0;

        TableDetails tableDetails = uriMatcherHelper.getTableDetails(uri);
        SQLiteDatabase db = database.getWritableDatabase();

        if (debugEnabled) {
            CPOrmLog.d("********* Bulk Insert **********");
            CPOrmLog.d("Uri: " + uri);
        }

        int count = 0;

        try {
            db.beginTransactionNonExclusive();
            String tableName = tableDetails.getTableName();
            for (int i = 0; i < length; i++) {

                db.insertOrThrow(tableName, null, values[i]);
                count++;

                if (count % 100 == 0)
                    db.yieldIfContendedSafely();
            }

            db.setTransactionSuccessful();

            notifyChanges(uri.buildUpon().appendQueryParameter(PARAMETER_CHANGE_TYPE, CPOrm.ChangeType.INSERT.toString()).build(), tableDetails);
        } finally {
            db.endTransaction();
        }

        return count;
    }

    @NonNull
    @Override
    public ContentProviderResult[] applyBatch(@NonNull ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {

        if (debugEnabled) {
            CPOrmLog.d("********* Apply Batch **********");
            CPOrmLog.d("Operations Count: " + operations.size());
        }

        isBatchOperation.set(true);
        changedUri.set(new LinkedHashSet<Uri>());

        boolean success = false;
        ContentProviderResult[] contentProviderResults = null;
        SQLiteDatabase db = database.getWritableDatabase();
        try {
            db.beginTransactionNonExclusive();
            contentProviderResults = super.applyBatch(operations);
            db.setTransactionSuccessful();
            success = true;
            return contentProviderResults;
        } finally {
            db.endTransaction();

            if(success && changedUri.get() != null) {
                for (Uri uri : changedUri.get()) {

                    if (uri != null) {
                        TableDetails tableDetails = uriMatcherHelper.getTableDetails(uri);
                        notifyChanges(uri, tableDetails);
                    }
                }
            }
            isBatchOperation.set(false);
            changedUri.remove();
        }
    }

    private String constructLimit(Uri uri) {

        String offsetParam = uri.getQueryParameter(PARAMETER_OFFSET);
        String limitParam = uri.getQueryParameter(PARAMETER_LIMIT);

        Integer offset = null;
        Integer limit = null;

        if (!TextUtils.isEmpty(offsetParam) && TextUtils.isDigitsOnly(offsetParam)) {
            offset = Integer.valueOf(offsetParam);
        }
        if (!TextUtils.isEmpty(limitParam) && TextUtils.isDigitsOnly(limitParam)) {
            limit = Integer.valueOf(limitParam);
        }

        if (limit == null && offset == null)
            return null;

        StringBuilder limitStatement = new StringBuilder();

        if (limit != null && offset != null) {
            limitStatement.append(offset);
            limitStatement.append(",");
            limitStatement.append(limit);
        } else if (limit != null) {
            limitStatement.append(limit);
        } else throw new IllegalArgumentException("A limit must also be provided when setting an offset");

        return limitStatement.toString();
    }

    private boolean shouldChangesBeNotified(TableDetails tableDetails, ContentValues contentValues) {

        boolean notify = false;

        for (String columnName : contentValues.keySet()) {

            TableDetails.ColumnDetails column = tableDetails.findColumn(columnName);
            if (column != null)
                notify = notify || column.notifyChanges();
        }

        return notify;
    }

    private void notifyChanges(Uri uri, TableDetails tableDetails) {

        if(!uri.getBooleanQueryParameter(PARAMETER_NOTIFY_CHANGES, true))
            return;

        Boolean sync = uri.getBooleanQueryParameter(PARAMETER_SYNC, true);
        getContext().getContentResolver().notifyChange(uri, null, sync);

        List<Class<?>> changeListeners = tableDetails.getChangeListeners();
        if (!changeListeners.isEmpty()) {

            int size = changeListeners.size();
            for (int i = 0; i < size; i++) {
                Class<?> changeListener = changeListeners.get(i);
                TableDetails changeListenerDetails = database.getTableDetailsCache().findTableDetails(getContext(), changeListener);

                if (changeListenerDetails == null)
                    continue;

                //Change listeners are registered on views, so the entire view needs to be updated if changes to its data occurs
                Uri changeUri = uriMatcherHelper.generateItemUri(changeListenerDetails);
                getContext().getContentResolver().notifyChange(changeUri, null, sync);
            }
        }
    }

    private boolean isBatchOperation(){
        return this.isBatchOperation.get() != null && this.isBatchOperation.get();
    }
}


text:
package java.security.cert;

import gnu.java.security.Engine;

import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.util.Collection;

/**
 * A CertStore is a read-only repository for certificates and
 * certificate revocation lists.
 *
 * @since JDK 1.4
 */
public class CertStore
{

  // Constants and fields.
  // ------------------------------------------------------------------------

  /** Service name for CertStore. */
  private static final String CERT_STORE = "CertStore";

  /** The underlying implementation. */
  private CertStoreSpi storeSpi;

  /** This implementation's provider. */
  private Provider provider;

  /** The name of this key store type. */
  private String type;

  /** The parameters used to initialize this instance, if any. */
  private CertStoreParameters params;

  // Constructor.
  // ------------------------------------------------------------------------

  /**
   * Create a new CertStore.
   *
   * @param storeSpi The underlying implementation.
   * @param provider The provider of this implementation.
   * @param type     The type of CertStore this class represents.
   * @param params   The parameters used to initialize this instance, if any.
   */
  protected CertStore(CertStoreSpi storeSpi, Provider provider, String type,
                      CertStoreParameters params)
  {
    this.storeSpi = storeSpi;
    this.provider = provider;
    this.type = type;
    this.params = params;
  }

// Class methods.
  // ------------------------------------------------------------------------

  /**
   * Returns the default certificate store type.
   *
   *
This value can be set at run-time via the security property
   * "certstore.type"; if not specified than the default type will be
   * "LDAP".
   *
   * @return The default CertStore type.
   */
  public static final synchronized String getDefaultType()
  {
    String type = null;
    type = (String) java.security.AccessController.doPrivileged(
      new PrivilegedAction() {
        public Object run() {
          return Security.getProperty("certstore.type");
        }
      }
    );
    if (type == null)
      type = "LDAP";
    return type;
  }

  /**
   * Get an instance of the given certificate store from the first
   * installed provider.
   *
   * @param type     The type of CertStore to create.
   * @param params   The parameters to initialize this cert store with.
   * @return The new instance.
   * @throws InvalidAlgorithmParameterException If the instance rejects
   *         the specified parameters.
   * @throws NoSuchAlgorithmException If no installed provider
   *         implements the specified CertStore.
   * @throws IllegalArgumentException If provider is null.
   */
  public static CertStore getInstance(String type, CertStoreParameters params)
    throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
  {
    Provider[] p = Security.getProviders();
    for (int i = 0; i < p.length; i++)
      {
        try
          {
            return getInstance(type, params, p[i]);
          }
        catch (NoSuchAlgorithmException e)
          {
	    // Ignored.
          }
      }

    throw new NoSuchAlgorithmException(type);
  }

  /**
   * Get an instance of the given certificate store from the named
   * provider.
   *
   * @param type     The type of CertStore to create.
   * @param params   The parameters to initialize this cert store with.
   * @param provider The name of the provider from which to get the
   *        implementation.
   * @return The new instance.
   * @throws InvalidAlgorithmParameterException If the instance rejects
   *         the specified parameters.
   * @throws NoSuchAlgorithmException If the specified provider does not
   *         implement the specified CertStore.
   * @throws NoSuchProviderException If no provider named
   *         provider is installed.
   * @throws IllegalArgumentException If provider is null.
   */
  public static CertStore getInstance(String type, CertStoreParameters params,
                                      String provider)
    throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
           NoSuchProviderException
  {
    Provider p = Security.getProvider(provider);
    if (p == null)
      throw new NoSuchProviderException(provider);
    return getInstance(type, params, p);
  }

  /**
   * Get an instance of the given certificate store from the given
   * provider.
   *
   * @param type     The type of CertStore to create.
   * @param params   The parameters to initialize this cert store with.
   * @param provider The provider from which to get the implementation.
   * @return The new instance.
   * @throws InvalidAlgorithmParameterException If the instance rejects
   *         the specified parameters.
   * @throws NoSuchAlgorithmException If the specified provider does not
   *         implement the specified CertStore.
   * @throws IllegalArgumentException If provider is null.
   */
  public static CertStore getInstance(String type, CertStoreParameters params,
                                      Provider provider)
    throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
  {
    if (provider == null)
      throw new IllegalArgumentException("null provider");

    try
      {
        return new CertStore((CertStoreSpi) Engine.getInstance(CERT_STORE,
          type, provider, new Object[] { params }), provider, type, params);
      }
    catch (ClassCastException cce)
      {
        throw new NoSuchAlgorithmException(type);
      }
    catch (java.lang.reflect.InvocationTargetException ite)
      {
        Throwable cause = ite.getCause();
        if (cause instanceof InvalidAlgorithmParameterException)
          throw (InvalidAlgorithmParameterException) cause;
        else
          throw new NoSuchAlgorithmException(type);
      }
  }

// Instance methods.
  // ------------------------------------------------------------------------

  /**
   * Return the type of certificate store this instance represents.
   *
   * @return The CertStore type.
   */
  public final String getType()
  {
    return type;
  }

  /**
   * Return the provider of this implementation.
   *
   * @return The provider.
   */
  public final Provider getProvider()
  {
    return provider;
  }

  /**
   * Get the parameters this instance was created with, if any. The
   * parameters will be cloned before they are returned.
   *
   * @return The parameters, or null.
   */
  public final CertStoreParameters getCertStoreParameters()
  {
    return params != null ? (CertStoreParameters) params.clone() : null;
  }

  /**
   * Get a collection of certificates from this CertStore, optionally
   * filtered by the specified CertSelector. The Collection returned may
   * be empty, but will never be null.
   *
   *
Implementations may not allow a null argument, even if no
   * filtering is desired.
   *
   * @param selector The certificate selector.
   * @return The collection of certificates.
   * @throws CertStoreException If the certificates cannot be retrieved.
   */
  public final Collection getCertificates(CertSelector selector)
    throws CertStoreException
  {
    return storeSpi.engineGetCertificates(selector);
  }

  /**
   * Get a collection of certificate revocation lists from this CertStore,
   * optionally filtered by the specified CRLSelector. The Collection
   * returned may be empty, but will never be null.
   *
   *
Implementations may not allow a null argument, even if no
   * filtering is desired.
   *
   * @param selector The certificate selector.
   * @return The collection of certificate revocation lists.
   * @throws CertStoreException If the CRLs cannot be retrieved.
   */
  public final Collection getCRLs(CRLSelector selector)
    throws CertStoreException
  {
    return storeSpi.engineGetCRLs(selector);
  }
}


text:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package mx.edu.beavercheeks.practica4.test;

import mx.edu.beavercheeks.practica4.controls.Remote;
import mx.edu.beavercheeks.practica4.controls.StereoRemote;
import mx.edu.beavercheeks.practica4.controls.TvRemote;
import mx.edu.beavercheeks.practica4.devices.Device;
import mx.edu.beavercheeks.practica4.devices.Stereo;
import mx.edu.beavercheeks.practica4.devices.Television;
import mx.edu.beavercheeks.practica4.exceptions.SystemDevicesExceptions;
import mx.edu.beavercheeks.practica4.familia.Familiar;
import mx.edu.beavercheeks.practica4.familia.Padre;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author rcamarena
 */
public class AppMainTest
{
    private Television tv;
    private Remote controlTV;
    private Device st;
    private Remote controlSt;
    private Remote[] controles;
    private Familiar padre;

    public AppMainTest() {
    }

    @BeforeClass
    public static void setUpClass() {
    }

    @AfterClass
    public static void tearDownClass() {
    }

    @Before
    public void setUp()
    {
        tv = new Television();
        controlTV = new TvRemote();
        st = new Stereo();
        controlSt = new StereoRemote();
        padre = new Padre();
        controles=new Remote[2];
        controles[0]=controlTV;
        controles[1]= controlSt ;

        padre.setControlRemoto(controles);
        controlTV = padre.getControlRemoto()[0];
        //controlTV.enciendeAparato(tv);
        controlTV.apagaAparato(tv);
        try
        {
            ((TvRemote) controlTV).cambiaCanal(tv, 25);
        }
        catch (SystemDevicesExceptions excepcion)
        {
            System.err.println("Error: " +excepcion.getMessage());
            excepcion.getStackTrace();
        }

    }

    @After
    public void tearDown() {
    }

    // TODO add test methods here.
    // The methods must be annotated with annotation @Test. For example:
    //
    // @Test
    // public void hello() {}

    @Test
    public void testApp()
    {
        assertSame(25, tv.getCanalActual());
    }
}


text:
.class final Lcom/android/internal/telephony/cat/BearerCSD$1;
.super Ljava/lang/Object;
.source "BearerCSD.java"

# interfaces
.implements Landroid/os/Parcelable$Creator;

# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
    value = Lcom/android/internal/telephony/cat/BearerCSD;
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x8
    name = null
.end annotation

.annotation system Ldalvik/annotation/Signature;
    value = {
        "Ljava/lang/Object;",
        "Landroid/os/Parcelable$Creator",
        "<",
        "Lcom/android/internal/telephony/cat/BearerCSD;",
        ">;"
    }
.end annotation

# direct methods
.method constructor <init>()V
    .locals 0

    .prologue
    .line 41
    invoke-direct/range {p0 .. p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method

# virtual methods
.method public createFromParcel(Landroid/os/Parcel;)Lcom/android/internal/telephony/cat/BearerCSD;
    .locals 2
    .parameter "in"

    .prologue
    .line 43
    new-instance v0, Lcom/android/internal/telephony/cat/BearerCSD;

    const/4 v1, 0x0

    invoke-direct {v0, p1, v1}, Lcom/android/internal/telephony/cat/BearerCSD;-><init>(Landroid/os/Parcel;Lcom/android/internal/telephony/cat/BearerCSD$1;)V

    return-object v0
.end method

.method public bridge synthetic createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
    .locals 1
    .parameter "x0"

    .prologue
    .line 41
    invoke-virtual {p0, p1}, Lcom/android/internal/telephony/cat/BearerCSD$1;->createFromParcel(Landroid/os/Parcel;)Lcom/android/internal/telephony/cat/BearerCSD;

    move-result-object v0

    return-object v0
.end method

.method public newArray(I)[Lcom/android/internal/telephony/cat/BearerCSD;
    .locals 1
    .parameter "size"

    .prologue
    .line 47
    new-array v0, p1, [Lcom/android/internal/telephony/cat/BearerCSD;

    return-object v0
.end method

.method public bridge synthetic newArray(I)[Ljava/lang/Object;
    .locals 1
    .parameter "x0"

    .prologue
    .line 41
    invoke-virtual {p0, p1}, Lcom/android/internal/telephony/cat/BearerCSD$1;->newArray(I)[Lcom/android/internal/telephony/cat/BearerCSD;

    move-result-object v0

    return-object v0
.end method


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>W-Index</title>
<meta name="date" content="2014-07-01">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Letter

Next Letter

Frames

No Frames

All Classes

A B C D E F G H I J K L M N O P Q R S T U V W X Z _

W

w - Variable in class org.objectweb.asm.xml.Processor.SAXWriter

w - Variable in class org.objectweb.asm.xml.Processor.SAXWriterFactory

WHILE - Static variable in class bramspr.BramsprLexer

WHILE - Static variable in class bramspr.BramsprParser

WHILE() - Method in class bramspr.BramsprParser.WhileStructureContext

whileStructure() - Method in class bramspr.BramsprParser.StructureContext

whileStructure() - Method in class bramspr.BramsprParser

WHITESPACE - Static variable in class bramspr.BramsprLexer

WHITESPACE - Static variable in class bramspr.BramsprParser

WHITESPACE_action(RuleContext, int) - Method in class bramspr.BramsprLexer

WIDE_INSN - Static variable in class org.objectweb.asm.ClassWriter

The type of the WIDE instruction.

write(ClassWriter, byte[], int, int, int) - Method in class org.objectweb.asm.Attribute

Returns the byte array form of this attribute.

writeAttributes(Attributes) - Method in class org.objectweb.asm.xml.Processor.SAXWriter

writeFrame() - Method in class org.objectweb.asm.MethodWriter

Compress and writes the current frame MethodWriter.frame in the StackMapTable
 attribute.

writeFrameType(Object) - Method in class org.objectweb.asm.MethodWriter

writeFrameTypes(int, int) - Method in class org.objectweb.asm.MethodWriter

Writes some types of the current frame MethodWriter.frame into the
 StackMapTableAttribute.

writeIdent() - Method in class org.objectweb.asm.xml.Processor.SAXWriter

writeItems(Collection<SerialVersionUIDAdder.Item>, DataOutput, boolean) - Static method in class org.objectweb.asm.commons.SerialVersionUIDAdder

Sorts the items in the collection and writes it to the data output stream

WRITER - Static variable in class org.objectweb.asm.ClassReader

True to enable bytecode writing support.

writeShort(byte[], int, int) - Static method in class org.objectweb.asm.MethodWriter

Writes a short value in the given byte array.

A B C D E F G H I J K L M N O P Q R S T U V W X Z _

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Letter

Next Letter

Frames

No Frames

All Classes


text:
pair <double,double> ObjectiveBPR::get_gradient(RecPred* rec_pred1, RecPred* rec_pred2){
  double pred_diff = rec_pred1->prediction - rec_pred2->prediction;
  double gradient = 0;
//  if (pred_diff>0)  gradient = -1 *  exp(-pred_diff) / (double) (1 + exp(-pred_diff));
  gradient = -1 *  1 / (double) (1 + exp(pred_diff));
  return make_pair(gradient,-gradient);
}


text:
..
 This work is licensed under a Creative Commons Attribution 3.0 Unported
 License.

 http://creativecommons.org/licenses/by/3.0/legalcode

================
Snapshot support
================

https://storyboard.openstack.org/#!/story/2008033

Problem description
===================

Snapshot is not a new thing, it was available for virtual machines for a
long time. Snapshot is useful for instance backup, image reusing, etc, but
there is no such support for bare metals as it's more complex than passing
the request to libvirt.

Bare metal snapshot may not match with virtual machines in speed and
efficiency, but it could address following requirements:

As an operator, I want to be able to back up a bare metal instance
periodically and when there is hardware failure, the same image can be
applied to another machine.

As an operator, I want to be able to build a master image from a post
customized instance, capture the system into an image and apply to other
similar machines.

Proposed change
===============

The proposal is to implement a similar process like deployment, when a node
is requested to do a snapshot, ironic prepares boot configuration then
triggers a netboot to the node, IPA lookups and ironic instructs IPA to
streaming the data of root disk to a remote storage.

The remote storage could be the host where the conductor is running if proper
service like NFS, HTTP, etc is configured. Or another host as long as both
conductor and IPA are able to access. The remote storage will act as an
intermediate storage, when the streaming is done, conductor will upload the
image to the image service and remove the image in the intermediate
storage.

The initial proposal is to utlilize HTTP WebDAV as remote storage, NFS and
other storage can be extended when this feature is implemented. When the
direct deploy interface is configured to download images from HTTP service,
it can be updated with WebDAV support.

Alternatives
------------

None

Data model impact
-----------------

A new hardware interface ``snapshot_interface`` will be added to support
different snapshot implementations.

State Machine Impact
--------------------

Add following states to the state machine:

* snapshot wait
* snapshotting
* snapshot failed

With following transitions:

* active -> snapshotting (on snapshot) Prepare boot and network
* snapshotting -> snapshot failed (on fail) On error
* snapshotting -> snapshot wait (on wait) Wait for ramdisk alive
* snapshot wait -> snapshotting (on resume) Image streaming and uploading
* snapshot wait -> snapshot failed (on fail) On timeout
* snapshot wait -> snapshot failed (on abort) On abort request
* snapshotting -> active (on done) Snapshot complete
* snapshot failed -> active (on abort) Abort a failed snapshot
* snapshot failed -> snapshotting (on snapshot) Retrigger a failed snapshot
* snapshot wait -> deleting (on deleted) Abort snapshot and undeploy
* snapshot failed -> deleting (on deleted) Abort and undeploy

REST API impact
---------------

The existing provision endpoint is used, a new verb ``snapshot`` will be
guarded by microversions.

* PUT /v1/nodes/{node_ident}/states/provision

  When the requested version is permitted, and node is in the active state,
  start to do a snapshot. An ``image_ref`` argument is required, which refers
  to a location where the snapshot image should be stored.

  If the ``image_ref`` is an UUID, it refers to the UUID of an image in the
  Image serivce, the image should be precreated before snapshot request and
  acts as a holder for receiving image data. When integrated with Compute
  service, the ``image_id`` is an argument passed to the driver interface
  ``snapshot()``.

  Example request::

    {
      "target": "snapshot",
      "image_ref": "66498c26-a9b5-496c-97a8-5bc08f256155"
    }

   The ``image_ref`` could be an URL in other forms for standalone usage,
   but not covered in this spec.

Other provision state transitions will use existing verbs.

Client (CLI) impact
-------------------

"openstack baremetal" CLI
~~~~~~~~~~~~~~~~~~~~~~~~~

The impact to CLI should be trivial, will have a new command:

* ``openstack baremetal node snapshot <node> ...``

"openstacksdk"
~~~~~~~~~~~~~~

openstacksdk will be enhanced to know the snapshot API version.

RPC API impact
--------------

Will introduce a new rpc interface ``do_node_snapshot``.

Driver API impact
-----------------

Adds an optional interface ``snapshot_interface``, initially implements
``fake``, ``no-snapshot``, and ``agent``.

.. code-block::python

    class SnapshotInterface(BaseInterface):
        """Interface for snapshot-related actions."""
        interface_type = "snapshot"

        @abc.abstractmethod
        def snapshot(self, task):
            """Perform a snapshot to the task's node.

            :param task: A TaskManager instance containing the node to act on.
            :returns: states.SNAPSHOTWAIT if snapshot is in progress asynchronously
                      or states.ACTIVE if it is complete.
            """

        @abc.abstractmethod
        def continue_snapshot(self, task):
            """Continue snapshot for async operation.

            :param task: A TaskManager instance containing the node to act on.
            """

        @abc.abstractmethod
        def clean_up(self, task):
            """Clean up the snapshot environment for the task's node.

            :param task: A TaskManager instance containing the node to act on.
            """

For the ``agent`` implementation, conductor host needs a WebDAV service to
receive image data from the IPA. When the first heartbeat is received,
ironic conductor sends command ``snapshot.stream_image`` with an URL to the
IPA to start the snapshotting. IPA find the root device and use proper methods
to dump disk data to the remote storage. The criterial for choosing the root
device is same with deployment, on the time of this writing, the root device
is the first available block device not less than 4GiB, or the first matched
device if the root device hint is specified.

There are two methods to utilize the WebDAV service:

* The WebDAV directory is mounted to the ramdisk, IPA uses ``qemu-img`` for
  snapshot, empty blocks will be bypassed so it provides better performance.
* IPA uses ``dd`` to dump the disk data to the WebDAV URL, when finished,
  ironic conductor needs to convert the raw image into proper format.

As the root device could be quite large and even larger than the available
space of conductor host, ``dd`` is not considered practical in the spec.

After the disk data is successfully retrieved, the conductor is responsible
to upload the image to the Image Service using the specified ``image_id`` and
remove the intermediate image.

Nova driver impact
------------------

Nova driver will need to implement the driver interface ``snapshot`` to
integrate with ironic. But before the integration the feature can be consumed
by ironic as long as the Image Service is available.

Ramdisk impact
--------------

For the ``agent`` implementation, a ``snapshot`` extension will be added to
the ironic-python-agent, when the WebDAV directory could be mounted,
``qemu-img`` is used for streaming disk data to the URL.

The snapshot extension will be defined as:

.. code-block::python

    class SnapshotExtension(base.BaseAgentExtension):
        @base.async_command('stream_image')
        def stream_image(self, url, image_name):
            """Stream disk data to the storage using provided information.

            :param url: string, the remote storage in URL format.
            :param image_name: string, the name of the image.
            """

Example arguments for an HTTP WebDAV connection:

* url: "http://10.10.1.1:8080/snapshots"
* image_name: "a830ebe1-67d4-448f-aa10-5bb33f3f3c02-snapshot.qcow2"

IPA will generate an URL to mount::

    mount -t davfs http://10.10.1.1:8080/snapshots /tmp/tmp5fjchif0

.. note::

   NFS connection is not covered but can be implemented after this feature
   is implemented. It will look like::

     mount -t nfs 10.10.1.1:/var/lib/ironic/snapshots /tmp/tmp5fjchif0

Security impact
---------------

The transfer of instance image from the target bare metal to image service
could have security risk since the data could be tampered or retrieved during
this process.

Other end user impact
---------------------

None

Scalability impact
------------------

None

Performance Impact
------------------

None

Other deployer impact
---------------------

None

Developer impact
----------------

None

Implementation
==============

Assignee(s)
-----------

Primary assignee:
  <kaifeng, kaifeng.w@gmail.com>

Other contributors:
  <TheJulia, juliaashleykreger@gmail.com>

Work Items
----------

* Equiping IPA with the ability of streaming disk data
* Spawning states and transitions to Ironic
* DB, RPC and API change
* Make Client/SDK aware of the feature
* Plug in with nova

Dependencies
============

None

Testing
=======

Will be covered by unit tests and tempest.

Upgrades and Backwards Compatibility
====================================

Should be backwards compatible.

Documentation Impact
====================

Documentation will be updated on this feature.

References
==========

* https://etherpad.opendev.org/p/PVG-ironic-snapshot-support


text:
package logbook.dto;

import java.util.HashSet;
import java.util.Set;

import logbook.config.bean.ShipGroupBean;
import logbook.internal.SallyArea;
import logbook.internal.ShipStyle;

/**
 * 所有艦娘一覧で使用するフィルター
 */
public final class ShipFilterDto extends AbstractDto {

    /** 名前 */
    public String nametext;
    /** 名前.正規表現を使用する */
    public boolean regexp;

    /** 艦種 */
    public Set<String> shipType = new HashSet<>(ShipStyle.get().values());

    /** グループ */
    public ShipGroupBean group;
    /** 出撃海域 */
    public SallyArea area;
    /** 装備 */
    public String itemname;
    /** 艦隊に所属 */
    public boolean onfleet = true;
    /** 艦隊に非所属 */
    public boolean notonfleet = true;
    /** 鍵付き */
    public boolean locked = true;
    /** 鍵付きではない */
    public boolean notlocked = true;
}


text:
namespace Microsoft.eShopOnContainers.Services.Catalog.API
{
    using global::Catalog.API.Infrastructure.Filters;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Infrastructure;
    using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
    using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
    using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
    using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
    using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.HealthChecks;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using System;
    using System.Data.SqlClient;
    using System.IO;
    using System.Data.Common;
    using System.Reflection;
    using global::Catalog.API.IntegrationEvents;
    using System.Threading.Tasks;

    public class Startup
    {
        public IConfigurationRoot Configuration { get; }

        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile($"settings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"settings.{env.EnvironmentName}.json", optional: true);

            if (env.IsDevelopment())
            {
                builder.AddUserSecrets(typeof(Startup).GetTypeInfo().Assembly);
            }

            builder.AddEnvironmentVariables();

            Configuration = builder.Build();
        }

        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.

            services.AddHealthChecks(checks =>
            {
                checks.AddSqlCheck("CatalogDb", Configuration["ConnectionString"]);
            });

            services.AddMvc(options =>
            {
                options.Filters.Add(typeof(HttpGlobalExceptionFilter));
            }).AddControllersAsServices();

            services.AddDbContext<CatalogContext>(options =>
            {
                options.UseSqlServer(Configuration["ConnectionString"],
                                     sqlServerOptionsAction: sqlOptions =>
                                     {
                                         sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
                                         //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
                                         sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                                     });
                // Changing default behavior when client evaluation occurs to throw.
                // Default in EF Core would be to log a warning when client evaluation is performed.
                options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
                //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
            });

            services.Configure<Settings>(Configuration);

            // Add framework services.
            services.AddSwaggerGen();
            services.ConfigureSwaggerGen(options =>
            {
                options.DescribeAllEnumsAsStrings();
                options.SingleApiVersion(new Swashbuckle.Swagger.Model.Info()
                {
                    Title = "eShopOnContainers - Catalog HTTP API",
                    Version = "v1",
                    Description = "The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample",
                    TermsOfService = "Terms Of Service"
                });
            });

            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials());
            });

            services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
                sp => (DbConnection c) => new IntegrationEventLogService(c));
            var serviceProvider = services.BuildServiceProvider();
            var configuration = serviceProvider.GetRequiredService<IOptionsSnapshot<Settings>>().Value;
            services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>();
            services.AddSingleton<IEventBus>(new EventBusRabbitMQ(configuration.EventBusConnection));
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            //Configure logs

            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseCors("CorsPolicy");

            app.UseMvcWithDefaultRoute();

            app.UseSwagger()
              .UseSwaggerUi();

            var context = (CatalogContext)app
                        .ApplicationServices.GetService(typeof(CatalogContext));

            WaitForSqlAvailability(context, loggerFactory);
            //Seed Data
            CatalogContextSeed.SeedAsync(app, loggerFactory)
            .Wait();

            var integrationEventLogContext = new IntegrationEventLogContext(
                new DbContextOptionsBuilder<IntegrationEventLogContext>()
                .UseSqlServer(Configuration["ConnectionString"], b => b.MigrationsAssembly("Catalog.API"))
                .Options);
            integrationEventLogContext.Database.Migrate();
        }

        private void WaitForSqlAvailability(CatalogContext ctx, ILoggerFactory loggerFactory, int? retry = 0)
        {
            int retryForAvailability = retry.Value;
            try
            {
                ctx.Database.OpenConnection();
            }
            catch(SqlException ex)
            {
                if (retryForAvailability < 10)
                {
                    retryForAvailability++;
                    var log = loggerFactory.CreateLogger(nameof(Startup));
                    log.LogError(ex.Message);
                    WaitForSqlAvailability(ctx, loggerFactory, retryForAvailability);
                }
            }
            finally {
                ctx.Database.CloseConnection();
            }

        }
    }
}