Partilhar via


Criar e aplicar o instantâneo inicial

Aplica-se a: SQL Server Instância Gerenciada de SQL do Azure

Este tópico descreve como criar e aplicar o instantâneo inicial no SQL Server usando o SQL Server Management Studio, o Transact-SQL ou o Replication Management Objects (RMO). Publicações de mesclagem que usam filtros com parâmetros exigem um instantâneo de duas partes. Para obter mais informações, consulte Criar um instantâneo para uma publicação de mesclagem com filtros com parâmetros.
Instantâneos são gerados pelo Agente de Instantâneo depois que uma publicação for criada. Eles podem ser gerados:

  • Imediatamente. Por padrão, um instantâneo para uma publicação de mesclagem é gerado imediatamente depois que a publicação seja criada no Assistente para Nova Publicação.
  • Em um momento agendado. Especifique um agendamento na página Agente de Instantâneo do Assistente para Nova Publicação ou ao usar procedimentos armazenados no RMO (Replication Management Object).
  • Manualmente. Execute o Agente de Instantâneo no prompt de comando ou no SQL Server Management Studio. Para obter mais informações sobre a execução de agentes, consulte Conceitos dos executáveis do Replication Agent ou Iniciar e interromper um Agente de Replicação (SQL Server Management Studio).

Para replicação de mesclagem, é gerado um instantâneo toda vez que o Agente de Instantâneo é executado. Para replicação transacional, a geração de instantâneo depende da configuração da propriedade de publicação de immediate_sync. Se a propriedade estiver definida como TRUE (padrão ao usar o Assistente para Nova Publicação), um instantâneo é gerado toda vez que o Agente de Instantâneo for executado e pode ser aplicado ao Assinante a qualquer momento. Se a propriedade estiver definida como FALSE (padrão ao usar sp_addpublication), o instantâneo só é gerado se uma assinatura nova for adicionada desde a última execução do Agente de Instantâneo; Assinantes devem esperar que o Agente de Instantâneo termine antes de poder sincronizar-se.

Por padrão, quando são gerados instantâneos, eles são salvados na pasta de instantâneo padrão localizada no Distribuidor. Você também pode salvar os arquivos de instantâneo em mídia removível, como discos removíveis, CD-ROMs ou em locais diferentes da pasta padrão do instantâneo. Adicionalmente, você poderá comprimir os arquivos para que sejam mais fáceis de armazenar e transferir, e executar os scripts antes ou depois de o instantâneo ser aplicado ao Assinante. Para obter mais informações sobre essas opções, consulte Snapshot Options.

Se o instantâneo for uma publicação de mesclagem que usa filtros com parâmetros, o instantâneo será criado usando um processo de duas partes. Primeiro é criado um instantâneo do esquema que contém os scripts de replicação e o esquema dos objetos publicados, mas não os dados. Cada assinatura é então inicializada com um instantâneo que inclui os scripts e o esquema copiados do instantâneo do esquema e os dados pertencentes à partição de assinatura. Para obter mais informações, consulte Snapshots for Merge Publications with Parameterized Filters.

Se o instantâneo for criado no Publicador e armazenado em um local padrão ou local alternativo de instantâneo, este poderá ser transferido ao Assinante e aplicado. O Agente de Distribuição (para replicação transacional ou de instantâneo) ou Agente de Mesclagem (para replicação de mesclagem) transferem o instantâneo e aplica o esquema e arquivos de dados ao banco de dados da assinatura no Assinante durante a sincronização inicial. Por padrão, a sincronização inicial acontecerá imediatamente depois que uma assinatura seja criada se você usar o Assistente para Nova Assinatura. Este comportamento é controlado pela opção Inicializar Quando na página Inicializar Assinaturas do assistente. Quando os instantâneos forem criados após a assinatura ser inicializada, eles não serão aplicados ao Assinante, a menos que a assinatura esteja marcada para reinicialização. Para obter mais informações, consulte Reinicializar as assinaturas.

Após o Agente de Distribuição ou Agente de Mesclagem aplicar o instantâneo inicial, o agente propaga atualizações subsequentes e outras modificações de dados. Quando instantâneos são distribuídos e aplicados a Assinantes, só esses Assinantes que estão à espera de instantâneos iniciais ou novos são afetados. Outros Assinantes daquela publicação (aqueles que já estejam recebendo inserções, atualizações, exclusões ou outras modificações aos dados publicados) não serão afetados.

Para exibir ou modificar o local padrão de pasta de instantâneo, consulte

Localização do instantâneo padrão

Especifique o local de instantâneo padrão na página Pasta de Instantâneo do Assistente para Configurar Distribuição. Para obter mais informações sobre como usar o assistente, consulte Configurar a publicação e a distribuição. Se você criar uma publicação em um servidor que não esteja configurada como Distributor, especifique um local de instantâneo padrão na página Pasta de Instantâneo do Assistente para Novas Publicações. Para obter mais informações sobre como usar esse assistente, consulte Criar uma publicação.

Modifique o local do instantâneo padrão na página Publicadores da caixa de diálogo Propriedades do Distribuidor – <Distribuidor>. Para obter mais informações, consulte Exibir e modificar as propriedades do Distribuidor e do Publicador. Defina a pasta de instantâneo para cada publicação na caixa de diálogo Propriedades da Publicação – <Publicação>. Para obter mais informações, consulte View and Modify Publication Properties.

Modificar a localização do instantâneo padrão

  1. Na página Publicadores da caixa de diálogo Propriedades do Distribuidor – <Distribuidor>, clique no botão de propriedades (...) para o Publicador para o qual você deseja alterar a localização do instantâneo padrão.

  2. Na caixa de diálogo Propriedades do Publicador – <Publisher>, digite um valor para a propriedade Pasta de Instantâneo Padrão.

    Observação

    O Snapshot Agent deve ter permissões de gravação para o diretório que você especificar, e o Distribution Agent ou Merge Agent devem ter permissões de leitura. Se as assinaturas pull forem usadas, será necessário especificar um diretório compartilhado como um caminho UNC, como \\computername\snapshot. Para obter mais informações, consulte Proteger a pasta de instantâneos.

  3. Selecione OK.

Create snapshot

Por padrão, se o SQL Server Agent estiver sendo executado, um instantâneo será gerado imediatamente pelo Agente de Instantâneo depois que a publicação seja criada com o Assistente para Nova Publicação. Por padrão, isso é então aplicado pelo Distribution Agent (para replicações transacionais e instantâneas) ou o Merge Agent (para assinaturas de mesclagem) para todas as assinaturas. Um instantâneo também pode ser gerado usando o SQL Server Management Studio e o Replication Monitor. Para obter informações sobre como iniciar o Replication Monitor, consulte Start the Replication Monitor (Iniciar o Replication Monitor).

Como usar o SQL Server Management Studio.

  1. Conecte-se ao Publicador no Management Studio e, em seguida, expanda o nó do servidor.
  2. Expanda a pasta Replicação e, em seguida, a pasta Publicações Locais .
  3. Clique com o botão direito do mouse na publicação para a qual você quer criar um instantâneo e, então, clique em Exibir Status do Snapshot Agent.
  4. Na caixa de diálogo Exibir Status do Snapshot Agent – <Publicação>, clique em Iniciar.
    Quando Snapshot Agent terminar de gerar o instantâneo, uma mensagem será exibida, tal como "[100%] Um instantâneo de 17 artigo(s) foi gerado."

No Replication Monitor

  1. No Replication Monitor, expanda um Grupo do publicador no painel esquerdo e, depois, expanda um Publicador.
  2. Clique com o botão direito do mouse na publicação para a qual você quer gerar um instantâneo e, então, clique em Gerar Instantâneo.
  3. Para visualizar o status do Agente de Instantâneo, clique na guia Agentes. Para obter informações mais detalhadas, clique com o botão direito do mouse no Agente de Instantâneo na grade e clique em Exibir Detalhes.

Usando o Transact-SQL

Instantâneos iniciais podem ser criados de forma programada criando e executando um trabalho do Agente de Instantâneo ou executando o arquivo executável do Agente de Instantâneo de um arquivo em lote. Depois da geração de um instantâneo inicial, ele é transferido para e aplicado no Assinante quando a assinatura é sincronizada pela primeira vez. Se o Agente de Instantâneo for executado de um prompt de comando ou um arquivo em lote, será preciso executar novamente o agente sempre que o instantâneo existente se tornar inválido.

Importante

Quando possível, solicite que os usuários insiram as credenciais de segurança em tempo de execução. Se for necessário armazenar credenciais em um arquivo de script, você deverá proteger o arquivo para impedir acesso não autorizado.

  1. Crie uma publicação de instantâneo, transacional ou de mesclagem. Para obter mais informações, consulte Criar uma assinatura.

  2. Execute sp_addpublication_snapshot (Transact-SQL). Especifique @publication e os seguintes parâmetros:

    • O@job_login que especifica as credenciais da Autenticação do Windows sob as quais o Snapshot Agent é executado no Distribuidor.

    • O@job_password, que é a senha para as credenciais do Windows fornecidas.

    • (Opcional) Um valor 0 para @publisher_security_mode se o agente usar Autenticação do SQL Server ao se conectar ao Publicador. Nesse caso, deve-se especificar também a informação de logon da Autenticação do SQL Server para @publisher_login e @publisher_password.

    • (Opcional) Uma agenda de sincronização para o trabalho do Snapshot Agent. Para obter mais informações, consulte Specify Synchronization Schedules.

    Importante

    Quando um Publicador é configurado com um Distribuidor remoto, os valores fornecidos para todos os parâmetros, inclusive job_login e job_password, são enviados ao Distribuidor como texto sem-formatação. Você deve criptografar a conexão entre o Publicador e seu Distribuidor remoto antes de executar esse procedimento armazenado. Para obter mais informações, confira Habilitar conexões criptografadas para o mecanismo de banco de dados (SQL Server Configuration Manager).

  3. Adicione artigos à publicação. Para obter mais informações, consulte Define an Article.

  4. No Publicador do banco de dados de publicação, execute sp_startpublication_snapshot (Transact-SQL) especificando o valor de publication da etapa 1.

Aplicar um instantâneo

Como usar o SQL Server Management Studio.

  1. Depois que um instantâneo for gerado, ele é aplicado pela sincronização da assinatura com o Distribution Agent ou Merge Agent:

    • Se o agente é definido para ser executado continuamente (o padrão para replicação transacional), o instantâneo é automaticamente aplicado após ser gerado.
    • Se o agente tiver execução agendada, o instantâneo será aplicado na próxima execução agendada do agente.
    • Se o agente tiver execução sob demanda, o instantâneo será aplicado na próxima vez que você executar o agente.

    Para obter mais informações sobre assinaturas de sincronização, consulte Synchronize a Push Subscription e Synchronize a Pull Subscription.

Usar o Transact-SQL

  1. Crie uma publicação de instantâneo, transacional ou de mesclagem. Para obter mais informações, consulte Criar uma assinatura.

  2. Adicione artigos à publicação. Para obter mais informações, consulte Define an Article.

  3. Do prompt de comando ou em um arquivo em lote, inicie o Replication Snapshot Agent executando snapshot.exe, especificando os seguintes argumentos de linha de comando:

    • -Publication
    • -Publisher
    • -Distributor
    • -PublisherDB
    • -ReplicationType

    Se você estiver usando Autenticação do SQL Server, deve-se também especificar os seguintes argumentos:

    • -DistributorLogin
    • -DistributorPassword
    • -DistributorSecurityMode = 0
    • -PublisherLogin
    • -PublisherPassword
    • -PublisherSecurityMode = 0

Exemplos (Transact-SQL)

Esse exemplo mostra como criar uma publicação transacional e adicionar um trabalho do Agente de Instantâneo para a nova publicação (usando variáveis de script sqlcmd ). O exemplo também inicia o trabalho.

-- To avoid storing the login and password in the script file, the values 
-- are passed into SQLCMD as scripting variables. For information about 
-- how to use scripting variables on the command line and in SQL Server
-- Management Studio, see the "Executing Replication Scripts" section in
-- the topic "Programming Replication Using System Stored Procedures".

DECLARE @publicationDB AS sysname;
DECLARE @publication AS sysname;
DECLARE @login AS sysname;
DECLARE @password AS sysname;
SET @publicationDB = N'AdventureWorks2022'; --publication database
SET @publication = N'AdvWorksCustomerTran'; -- transactional publication name
SET @login = $(Login);
SET @password = $(Password);

USE [AdventureWorks]

-- Enable transactional and snapshot replication on the publication database.
EXEC sp_replicationdboption 
  @dbname = @publicationDB, 
  @optname = N'publish',
  @value = N'true';

-- Execute sp_addlogreader_agent to create the agent job. 
EXEC sp_addlogreader_agent 
  @job_login = @login, 
  @job_password = @password,
  -- Explicitly specify the security mode used when connecting to the Publisher.
  @publisher_security_mode = 1;

-- Create new transactional publication, using the defaults. 
USE [AdventureWorks2022]
EXEC sp_addpublication 
  @publication = @publication, 
  @description = N'transactional publication';

-- Create a new snapshot job for the publication, using the defaults.
EXEC sp_addpublication_snapshot 
  @publication = @publication,
  @job_login = @login,
  @job_password = @password;

-- Start the Snapshot Agent job.
EXEC sp_startpublication_snapshot @publication = @publication;
GO

Esse exemplo cria uma publicação de mesclagem e adiciona um trabalho do Snapshot Agent (usando variáveis sqlcmd ) para a publicação. Esse exemplo também inicia o trabalho.

-- To avoid storing the login and password in the script file, the value 
-- is passed into SQLCMD as a scripting variable. For information about 
-- how to use scripting variables on the command line and in SQL Server
-- Management Studio, see the "Executing Replication Scripts" section in
-- the topic "Programming Replication Using System Stored Procedures".

DECLARE @publicationDB AS sysname;
DECLARE @publication AS sysname;
DECLARE @login AS sysname;
DECLARE @password AS sysname;
SET @publicationDB = N'AdventureWorks2022'; 
SET @publication = N'AdvWorksSalesOrdersMerge'; 
SET @login = $(Login);
SET @password = $(Password);

-- Enable merge replication on the publication database.
USE master
EXEC sp_replicationdboption 
  @dbname = @publicationDB, 
  @optname=N'merge publish',
  @value = N'true';

-- Create new merge publication, using the defaults. 
USE [AdventureWorks]
EXEC sp_addmergepublication 
  @publication = @publication, 
  @description = N'Merge publication.';

-- Create a new snapshot job for the publication, using the defaults.
EXEC sp_addpublication_snapshot 
  @publication = @publication,
  @job_login = @login,
  @job_password = @password;

-- Start the Snapshot Agent job.
EXEC sp_startpublication_snapshot @publication = @publication;
GO

Os seguintes argumentos de linha de comando iniciam o Snapshot Agent para gerar o instantâneo para uma publicação de mesclagem.

Observação

Quebras de linhas foram adicionadas para melhorar a legibilidade. Em um arquivo em lotes, devem ser feitos comandos em uma única linha.

  
REM -- Declare variables  
SET Publisher=%InstanceName%  
SET PublicationDB=AdventureWorks2022   
SET Publication=AdvWorksSalesOrdersMerge   
  
REM --Start the Snapshot Agent to generate the snapshot for AdvWorksSalesOrdersMerge.  
"C:\Program Files\Microsoft SQL Server\120\COM\SNAPSHOT.EXE" -Publication %Publication%   
-Publisher %Publisher% -Distributor %Publisher% -PublisherDB %PublicationDB%   
-ReplicationType 2 -OutputVerboseLevel 1 -DistributorSecurityMode 1  
  

Usando o RMO (Replication Management Objects)

O Agente de Instantâneo gera instantâneos depois da criação da publicação. É possível gerar esses instantâneos de forma programada usando o RMO (Replication Management Objects) e o acesso de código direto para as funcionalidades do agente de replicação. Os objetos usados dependem do tipo de replicação. O Snapshot Agent pode ser iniciado usando o objeto SnapshotGenerationAgent ou usando de forma assíncrona o trabalho do agente. Depois da geração do instantâneo inicial, ele é transferido para o Assinante, onde é aplicado quando a assinatura é sincronizada pela primeira vez. Será necessário executar novamente o agente sempre que o instantâneo existente não mais contiver dados válidos e atualizados. Para obter mais informações, consulte Maintain Publications (Manter publicações).

Importante

Quando possível, solicite que os usuários insiram as credenciais de segurança em tempo de execução. Se for preciso armazenar credenciais, use os serviços criptográficos fornecidos pelo Microsoft Windows .NET Framework.

Para gerar o instantâneo inicial de uma publicação de instantâneo ou transacional por meio da iniciação do trabalho do Snapshot Agent (assíncrono)

  1. Crie uma conexão com o Publicador usando a classe ServerConnection .

  2. Criar uma instância da classe TransPublication. Defina as propriedades Name e DatabaseName para a publicação, e a propriedade ConnectionContext para a conexão criada na etapa 1.

  3. Chame o método LoadProperties para carregar as propriedades remanescentes do objeto. Se esse método retornar false, as propriedades de publicação na etapa 2 foram definidas incorretamente ou a publicação não existe.

  4. Se o valor de SnapshotAgentExists for false, chame CreateSnapshotAgent para criar o trabalho do Snapshot Agent para essa publicação.

  5. Chame o método StartSnapshotGenerationAgentJob para iniciar o trabalho de agente que gera o instantâneo para essa publicação.

  6. (Opcional) Quando o valor de SnapshotAvailable for true, o instantâneo estará disponível a Assinantes.

Para gerar o instantâneo inicial de uma publicação de instantâneo ou transacional por meio da execução do Snapshot Agent (síncrono)

  1. Crie uma instância da classe SnapshotGenerationAgent e defina as seguintes propriedades necessárias:

  2. Defina um valor de Transactional ou Snapshot para ReplicationType.

  3. Chame o método GenerateSnapshot .

Para gerar o instantâneo inicial para uma publicação de mesclagem iniciando o trabalho do Snapshot Agent (assíncrono)

  1. Crie uma conexão com o Publicador usando a classe ServerConnection .

  2. Criar uma instância da classe MergePublication. Defina as propriedades Name e DatabaseName para a publicação, e a propriedade ConnectionContext para a conexão criada na etapa 1.

  3. Chame o método LoadProperties para carregar as propriedades remanescentes do objeto. Se esse método retornar false, as propriedades de publicação na etapa 2 foram definidas incorretamente ou a publicação não existe.

  4. Se o valor de SnapshotAgentExists for false, chame CreateSnapshotAgent para criar o trabalho do Snapshot Agent para essa publicação.

  5. Chame o método StartSnapshotGenerationAgentJob para iniciar o trabalho de agente que gera o instantâneo para essa publicação.

  6. (Opcional) Quando o valor de SnapshotAvailable for true, o instantâneo estará disponível a Assinantes.

Para gerar o instantâneo inicial de uma publicação de mesclagem pela execução do Snapshot Agent (síncrono)

  1. Crie uma instância da classe SnapshotGenerationAgent e defina as seguintes propriedades necessárias:

  2. Defina um valor de Merge para ReplicationType.

  3. Chame o método GenerateSnapshot .

Exemplos (RMO)

Esse exemplo executa o Agente de Instantâneo sincronicamente para gerar o instantâneo inicial para uma publicação transacional.

// Set the Publisher, publication database, and publication names.
string publicationName = "AdvWorksProductTran";
string publicationDbName = "AdventureWorks2022";
string publisherName = publisherInstance;
string distributorName = publisherInstance;

SnapshotGenerationAgent agent;

try
{
    // Set the required properties for Snapshot Agent.
    agent = new SnapshotGenerationAgent();
    agent.Distributor = distributorName;
    agent.DistributorSecurityMode = SecurityMode.Integrated;
    agent.Publisher = publisherName;
    agent.PublisherSecurityMode = SecurityMode.Integrated;
    agent.Publication = publicationName;
    agent.PublisherDatabase = publicationDbName;
    agent.ReplicationType = ReplicationType.Transactional;

    // Start the agent synchronously.
    agent.GenerateSnapshot();

}
catch (Exception ex)
{
    // Implement custom application error handling here.
    throw new ApplicationException(String.Format(
        "A snapshot could not be generated for the {0} publication."
        , publicationName), ex);
}
' Set the Publisher, publication database, and publication names.
Dim publicationName As String = "AdvWorksProductTran"
Dim publicationDbName As String = "AdventureWorks2022"
Dim publisherName As String = publisherInstance
Dim distributorName As String = publisherInstance

Dim agent As SnapshotGenerationAgent

Try
    ' Set the required properties for Snapshot Agent.
    agent = New SnapshotGenerationAgent()
    agent.Distributor = distributorName
    agent.DistributorSecurityMode = SecurityMode.Integrated
    agent.Publisher = publisherName
    agent.PublisherSecurityMode = SecurityMode.Integrated
    agent.Publication = publicationName
    agent.PublisherDatabase = publicationDbName
    agent.ReplicationType = ReplicationType.Transactional

    ' Start the agent synchronously.
    agent.GenerateSnapshot()

Catch ex As Exception
    ' Implement custom application error handling here.
    Throw New ApplicationException(String.Format( _
     "A snapshot could not be generated for the {0} publication." _
     , publicationName), ex)
End Try

Esse exemplo inicia de forma assíncrona o trabalho do agente sincronicamente para gerar o instantâneo inicial para uma publicação transacional.

// Set the Publisher, publication database, and publication names.
string publicationName = "AdvWorksProductTran";
string publicationDbName = "AdventureWorks2022";
string publisherName = publisherInstance;

TransPublication publication;

// Create a connection to the Publisher using Windows Authentication.
ServerConnection conn;
conn = new ServerConnection(publisherName);

try
{
    // Connect to the Publisher.
    conn.Connect();

    // Set the required properties for an existing publication.
    publication = new TransPublication();
    publication.ConnectionContext = conn;
    publication.Name = publicationName;
    publication.DatabaseName = publicationDbName;

    if (publication.LoadProperties())
    {
        // Start the Snapshot Agent job for the publication.
        publication.StartSnapshotGenerationAgentJob();
    }
    else
    {
        throw new ApplicationException(String.Format(
            "The {0} publication does not exist.", publicationName));
    }
}
catch (Exception ex)
{
    // Implement custom application error handling here.
    throw new ApplicationException(String.Format(
        "A snapshot could not be generated for the {0} publication."
        , publicationName), ex);
}
finally
{
    conn.Disconnect();
}
' Set the Publisher, publication database, and publication names.
Dim publicationName As String = "AdvWorksProductTran"
Dim publicationDbName As String = "AdventureWorks2022"
Dim publisherName As String = publisherInstance

Dim publication As TransPublication

' Create a connection to the Publisher using Windows Authentication.
Dim conn As ServerConnection
conn = New ServerConnection(publisherName)

Try
    ' Connect to the Publisher.
    conn.Connect()

    ' Set the required properties for an existing publication.
    publication = New TransPublication()
    publication.ConnectionContext = conn
    publication.Name = publicationName
    publication.DatabaseName = publicationDbName

    If publication.LoadProperties() Then
        ' Start the Snapshot Agent job for the publication.
        publication.StartSnapshotGenerationAgentJob()
    Else
        Throw New ApplicationException(String.Format( _
         "The {0} publication does not exist.", publicationName))
    End If
Catch ex As Exception
    ' Implement custom application error handling here.
    Throw New ApplicationException(String.Format( _
     "A snapshot could not be generated for the {0} publication." _
     , publicationName), ex)
Finally
    conn.Disconnect()
End Try

Bloqueio ao aplicar o instantâneo inicial

Se você tiver várias publicações, que publicam dados em um banco de dados nos assinantes, ao aplicar os instantâneos iniciais, você perceberá que apenas uma publicação pode aplicar seu instantâneo por vez.

Você pode ver um recurso de espera semelhante ao seguinte ao analisar a atividade do SQL:

APP: 18:16384:[snapshot_delivery_in_progress_Tr]:(9bcdaf92)
APP: 5:16384:[snapshot_delivery_in_progress_Er]:(3c3b7db9
)

A consulta do comportamento de bloqueio pode mostrar recursos semelhantes aos seguintes:

APP 16384:[appname]:(fbe42d68) XAPP 16384:[snapshot_del]:(9bcdaf92) X

Este comportamento ocorre por design. Isso ocorre porque um bloqueio de aplicativo é usado para impedir que vários agentes de replicação apliquem simultaneamente instantâneos de diferentes publicações ao mesmo banco de dados de assinantes. Como o bloqueio do aplicativo contém o nome do banco de dados do assinante, todas as publicações que forem publicadas no mesmo banco de dados do assinante serão afetadas. O resultado é que apenas um instantâneo pode ser inserido no banco de dados do assinante em um determinado momento.

Bloqueios exclusivos são usados nessa situação para ajudar a evitar a possibilidade de os agentes de replicação ficarem bloqueados uns com os outros.

Para contornar esse problema, especifique um banco de dados de assinantes diferente para cada publicação.