O WebSphere eXtreme Scale faz uma cópia do valor com base nas configurações de CopyMode disponíveis. Determine qual configuração funciona melhor para seus requisitos de implementação.
É possível usar o método setCopyMode(CopyMode, valueInterfaceClass) da API BackingMap para configurar o modo de cópia para um dos seguintes campos estáticos finais que estão definidos na classe com.ibm.websphere.objectgrid.CopyMode.
Quando um aplicativo usa a interface ObjectMap para obter uma referência para uma entrada de mapa, use essa referência somente dentro da transação da grade de dados que obteve a referência. O uso da referência em uma transação diferente pode gerar erros. Por exemplo, se você usar a estratégia de bloqueio pessimista para o BackingMap, uma chamada de método get ou getForUpdate adquire um bloqueio S (compartilhado) ou U (atualização), dependendo da transação. O método get retorna a referência ao valor e o bloqueio que foi obtido é liberado quando a transação é concluída. A transação deve chamar o método get ou getForUpdate para bloquear a entrada do mapa em uma transação diferente. Cada transação deve obter sua própria referência para o valor chamando o método get ou getForUpdate em vez de reutilizar a mesma referência de valor em múltiplas transações.
Ao usar um mapa associado a uma entidade da API EntityManager, o mapa sempre retorna os objetos Tuple da entidade diretamente sem fazer uma cópia, a menos que o modo de cópia COPY_TO_BYTES esteja sendo usado. É importante que o CopyMode seja atualizado ou que a Tupla seja copiada apropriadamente ao fazer alterações.
O modo COPY_ON_READ_AND_COMMIT é o modo padrão. O argumento valueInterfaceClass é ignorado quando este modo é utilizado. Esse modo assegura que um aplicativo não contém uma referência ao objeto de valor que está no BackingMap. Em vez disso, o aplicativo está sempre trabalhando com uma cópia do valor que está no BackingMap. O modo COPY_ON_READ_AND_COMMIT assegura que o aplicativo nunca possa danificar os dados que estão em cache no BackingMap. Quando uma transação do aplicativo chama um método ObjectMap.get para uma chave especificada e é o primeiro acesso da entrada do ObjectMap para essa chave, será retornada uma cópia do valor. Quando a transação for confirmada, todas as alterações feitas pelo aplicativo são copiadas no BackingMap para assegurar que o aplicativo não tenha uma referência ao valor confirmado no BackingMap.
O modo COPY_ON_READ aprimora o desempenho no modo COPY_ON_READ_AND_COMMIT, eliminando a cópia que ocorre quando uma transação é confirmada. O argumento valueInterfaceClass é ignorado quando este modo é utilizado. Para preservar a integridade dos dados do BackingMap, o aplicativo assegura que cada referência que ele possui para uma entrada será destruída após a confirmação da transação. Com esse modo, o método ObjectMap.get retorna uma cópia do valor em vez de retornar uma referência ao valor para assegurar que essas alterações feitas pelo aplicativo no valor não afetem o valor de BackingMap até que a transação seja confirmada. No entanto, quando a transação não é confirmada, não é feita uma cópia de alterações. Em vez disso, a referência à cópia que foi retornada pelo método ObjectMap.get é armazenada no BackingMap. O aplicativo destrói todas as referências de entrada do mapa após a confirmação da transação. Se o aplicativo não destruir as referências de entrada do mapa, o aplicativo pode fazer com que os dados em cache no BackingMap sejam danificados. Se um aplicativo estiver utilizando este modo e tiver problemas, vá para o modo COPY_ON_READ_AND_COMMIT para verificar se o problema ainda existe. Se o problema não existir mais, isto indica que o aplicativo está falhando ao destruir todas as suas referências após a confirmação da transação.
O modo COPY_ON_WRITE aprimora o desempenho no modo COPY_ON_READ_AND_COMMIT, eliminando a cópia que ocorre quando o método ObjectMap.get é chamado pela primeira vez por uma transação para uma chave especificada. O método ObjectMap.get retorna um proxy para o valor em vez de uma referência direta ao objeto de valor. O proxy assegura que não seja feita uma cópia do valor, a menos que o aplicativo chame um método set na interface de valor especificada pelo argumento valueInterfaceClass. O proxy fornece uma cópia na implementação de gravação. Quando uma transação é confirmada, o BackingMap examina o proxy para determinar se foi feita alguma cópia como resultado da chamada de um método set. Se tiver sido feita uma cópia, a referência a essa cópia será armazenada no BackingMap. A grande vantagem deste modo é que um valor nunca é copiado durante uma leitura ou em uma confirmação quando a transação nunca chama um método set para alterar o valor.
Os modos COPY_ON_READ_AND_COMMIT e COPY_ON_READ fazem uma cópia detalhada quando um valor é recuperado do ObjectMap. Se um aplicativo atualizar apenas alguns dos valores recuperados em uma transação, este modo não será o ideal. O modo COPY_ON_WRITE suporta este comportamento de maneira eficiente, mas requer que o aplicativo use um padrão simples. Os objetos de valor devem suportar uma interface. O aplicativo deve usar os métodos nessa interface quando estiver interagindo com o valor em uma sessão. Se este for o caso, os proxies serão criados para os valores retornados ao aplicativo. O proxy possui uma referência ao valor real. Se o aplicativo executa operações de leitura apenas, as operações de leitura sempre executam contra a cópia real. Se o aplicativo modificar um atributo no objeto, o proxy fará uma cópia do objeto real e, em seguida, modificará a cópia. O proxy então utiliza a cópia desse ponto em diante. O uso das cópia permite que a operação de cópia seja completamente evitada para objetos que são apenas de leitura pelo aplicativo. Todas as operações de modificação devem começar com o prefixo configurado. Os Enterprise JavaBeans normalmente são codificados para usarem este estilo de nomenclatura de métodos para métodos que modificam os atributos dos objetos. Esta convenção deve ser seguida. Todos os objetos modificados são copiados no momento em que forem modificados pelo aplicativo. Este cenário de leitura e gravação é o cenário mais eficiente suportado pelo eXtreme Scale. Para configurar um mapa para utilizar o modo COPY_ON_WRITE, utilize o seguinte exemplo: Nesse exemplo, o aplicativo armazena objetos Person que são chaveados utilizando o nome no Mapa. O objeto pessoal é representado no seguinte fragmento de código.
class Person {
String name;
int age;
public Person() {
}
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
public void setAge(int a) {
age = a;
}
public int getAge() {
return age;
}
}
O aplicativo utiliza apenas a interface IPerson quando interage com valores que são recuperados de um ObjectMap. Modifique o objeto para utilizar uma interface como no exemplo a seguir.
interface IPerson
{
void setName(String n);
String getName();
void setAge(int a);
int getAge();
}
// Modificar Person para implementar a interface IPerson
class Person implements IPerson {
...
}
ObjectGrid dg = ...;
BackingMap bm = dg.defineMap("PERSON");
// use COPY_ON_WRITE for this Map with
// IPerson as the valueProxyInfo Class
bm.setCopyMode(CopyMode.COPY_ON_WRITE,IPerson.class);
// The application should then use the following
// pattern when using the PERSON Map.
Session sess = ...;
ObjectMap person = sess.getMap("PERSON");
...
sess.begin();
// the application casts the returned value to IPerson and not Person
IPerson p = (IPerson)person.get("Billy");
p.setAge( p.getAge() + 1 );
...
// make a new Person and add to Map
Person p1 = new Person();
p1.setName("Bobby");
p1.setAge(12);
person.insert(p1.getName(), p1);
sess.commit();
// the following snippet WON'T WORK. Will result in ClassCastException
sess.begin();
// the mistake here is that Person is used rather than
// IPerson
Person a = (Person)person.get("Bobby");
sess.commit();
É possível lançar o proxy para dois tipos. A última parte do trecho de código anterior demonstra o que não é permitido no modo COPY_ON_WRITE. O aplicativo recupera o registro do Bobby e tenta converter o registro para um objeto Person. Esta ação falha com uma exceção de lançamento de classe, porque o proxy retornado não é um objeto Person. O proxy retornado implementa o objeto IPerson e ValueProxyInfo.
A interface ValueProxyInfo e o suporte de atualização parcial: Esta interface permite que um aplicativo recupere o valor somente leitura consolidado referenciado pelo proxy ou o conjunto de atributos que foram modificados durante esta transação.
public interface ValueProxyInfo {
List /**/ ibmGetDirtyAttributes();
Object ibmGetRealValue();
}
O método ibmGetRealValue retorna uma cópia de somente leitura do objeto. O aplicativo não deve modificar este valor. O método ibmGetDirtyAttributes retorna uma lista de sequências que representam os atributos que foram modificados pelo aplicativo durante essa transação. O principal caso de uso para o método ibmGetDirtyAttributes está em um Java database connectivity (JDBC) ou um carregador baseado em CMP. Apenas os atributos que estão denominados na lista precisam ser atualizados na instrução SQL ou no objeto mapeado para a tabela. Essa prática leva a um SQL mais eficiente gerado pelo Carregador. Quando uma transação de cópia na gravação é confirmada e se um carregador for conectado, o carregador poderá lançar os valores dos objetos modificados na interface ValueProxyInfo para obter essas informações.
Manipulação do método equals ao usar COPY_ON_WRITE ou proxies: Por exemplo, o código a seguir constrói um objeto Person e, então, o insere em um ObjectMap. Em seguida, ele recupera o mesmo objeto utilizando o método ObjectMap.get. O valor é lançado para a interface. Se o valor for lançado na interface Person, isto resultará em uma exceção ClassCastException, porque o valor retornado é um proxy que implementa a interface IPerson e não é um objeto Person. A verificação de igualdade falha ao utilizar a operação == porque eles não são o mesmo objeto.
session.begin();
// novo objeto Person
Person p = new Person(...);
personMap.insert(p.getName, p);
// recupere-o novamente, lembre-se de utilizar a interface para o lançamento
IPerson p2 = personMap.get(p.getName());
if(p2 == p) {
// they are the same
} else {
// they are not
}
Outra consideração é quando é necessário substituir o método equals. O método equals deve verificar se o argumento é um objeto que implementa a interface IPerson e lança o argumento para ser um objeto IPerson. Como o argumento pode ser um proxy que implementa a interface IPerson, você deve usar os métodos getAge e getName ao comparar as variáveis da instância por igualdade. Consulte o seguinte exemplo:
{
if ( obj == null ) return false;
if ( obj instanceof IPerson ) {
IPerson x = (IPerson) obj;
return ( age.equals( x.getAge() ) && name.equals( x.getName() ) )
}
return false;
}
Requisitos de configuração ObjectQuery e HashIndex: Ao usar o COPY_ON_WRITE com os plug-ins ObjectQuery ou HashIndex, você deve configurar o esquema ObjectQuery e o plug-in HashIndex para acessar os objetos usando os métodos de propriedade, que é o padrão. Se você tiver configurado o acesso ao campo, o mecanismo de consulta e o índice tentarão acessar os campos no objeto proxy, o que sempre retorna nulo ou 0 porque a instância do objeto é um proxy.
O modo NO_COPY permite que um aplicativo obtenha melhorias de desempenho, mas requer que o aplicativo nunca modifique um objeto de valor que seja obtido com o uso de um método ObjectMap.get. O argumento valueInterfaceClass será ignorado quando este modo for usado. Se este modo for utilizado, nunca será feita uma cópia do valor. Se o aplicativo modificar alguma instância do objeto de valor que seja recuperada de ou incluída no ObjectMap, os dados no BackingMap serão corrompidos. O modo NO_COPY é útil, principalmente para mapas de leitura nos quais os dados nunca são modificados pelo aplicativo. Se o aplicativo estiver utilizando este modo e tiver problemas, vá para o modo COPY_ON_READ_AND_COMMIT para verificar se o problema ainda existe. Se o problema não existir mais, isto indica que o aplicativo está modificando o valor retornado pelo método ObjectMap.get, durante ou após a confirmação da transação. Todos os mapas associados às entidades da API EntityManager automaticamente usam este modo, independentemente do que está especificado na configuração do eXtreme Scale.
Todos os mapas associados às entidades da API EntityManager automaticamente usam este modo, independentemente do que está especificado na configuração do eXtreme Scale.
É possível armazenar objetos em um formato serializado em vez do formato POJO. Ao usar a configuração COPY_TO_BYTES, é possível reduzir a área de cobertura da memória que um gráfico grande de objetos pode consumir. Para obter informações adicionais, consulte Aprimorando o Desempenho com Mapas de Matriz de Byte.
Com o modo COPY_TO_BYTES_RAW, é possível acessar diretamente o formulário serializado de seus dados. Este modo de cópia oferece uma maneira eficiente para você interagir com bytes serializados, que permite ignorar o processo de desserialização para acessar objetos na memória.
No arquivo XML descritor do ObjectGrid, é possível configurar o modo de cópia para COPY_TO_BYTES, e configurar programaticamente o modo de cópia para COPY_TO_BYTES_RAW nas instâncias em que você desejar acessar os dados brutos serializados. Configure o modo de cópia COPY_TO_BYTES_RAW no arquivo XML descritor do ObjectGrid apenas quando seu aplicativo usar os dados brutos como parte de um processo de aplicativo principal.Ocorrem erros quando um aplicativo tenta melhorar o desempenho utilizando o modo de cópia COPY_ON_READ, COPY_ON_WRITE ou NO_COPY, conforme descrito acima. Os erros intermitentes não ocorrem quando você altera o modo de cópia para COPY_ON_READ_AND_COMMIT.
Problema
O problema pode ser devido a dados danificados no mapa do ObjectGrid, que é um resultado de um aplicativo que está violando o contrato de programação do modo de cópia que está sendo utilizado. O dano dos dados pode causar erros imprevisíveis de forma intermitente ou de maneira inexplicada ou inesperada.
Solução
O aplicativo deve estar em conformidade com o contrato de programação estabelecido para o modo de cópia em utilização. Para os modos de cópia COPY_ON_READ e COPY_ON_WRITE, o aplicativo utiliza uma referência a um objeto de valor fora do escopo da transação a partir do qual a referência foi obtida. Para utilizar esses modos, o aplicativo deverá excluir a referência ao objeto de valor depois da conclusão da transação e obter uma nova referência em cada transação que acesse tal objeto. Para o modo de cópia NO_COPY, o aplicativo deve nunca alterar o objeto de valor. Nesse caso, programe o aplicativo de modo que ele não altere o objeto de valor ou configure-o para utilizar um modo de cópia diferente.