Prevalência com Swap e/ou Passivation

66 respostas
saoj

Algumas pessoas tem levantado a bola que o Space4J/Prevayler deveriam ter um esquema de Swap para poder comportar mais dados que o limite da RAM.

Uma idéia seria monitorar objetos que estão a muito tempo sem ser acessados e dar um passivate neles, ou seja, tirar eles da memória e colocá-los em disco. Como EJB faz !!!

Será que vale a pena ir por aí ???

Um abraço,

Sergio Oliveira

66 Respostas

cv1

Nao sei se vale a pena, por dois motivos:

  • Voce teria que colocar dynamic proxies pra todos os objetos no seu sistema, e os proxies em si podem ser as vezes mais gordos do que os proprios objetos, sem contar na memoria a mais que vc iria gastar mantendo uma LRU (least-recently-used) pra todos os objetos.

  • Quando “despassivar” um objeto? A resposta mais obvia (“quando ele for usado de novo, oras!”) pode trazer uma degradação de performance imensa (pense no que aconteceria ao iterar sobre uma lista de objetos grande, e ter que deserializar objeto por objeto… nada bom, nada bom).

Outro ponto é a inserção dos proxies, em si… haja factory! :smiley:

urubatan

eu acho que se fosse implementada uma solução deste tipo, ai sim, seriam soluções perfeitas para persistir dados,
o problema para isto, é que eles não tem nenhuma relação com a maneira pela qual os dados são acessados, assim fica dificil de fazer um Lazy loading para carregar os dados depois, para tirar eles da memoria seria bem fácil, é só utilizar Week Reference (se não me engano é assim que se escreve, depois procuro no amança burro :slight_smile:

cv1

O problema não está em usar Weak References, urubatan… mas sim em onde colocar essas weakrefs, e como fazer o lazy loading direitinho…

Uma ideia que me veio à cabeça agora é ter um dynamic proxy realmente inteligente, que entende as chamadas Load Policies… ou seja, voce pode especificar pra ele grupos de objetos que devem ser carregados de uma vez soh…

…mas aí vc está implementando um bicho beeeeeeem grande, e bem complexo :? - nada contra, mas já fica avisado desde já que o esforço não é nada trivial! :smiley:

urubatan

é verdade, não tinha pensado nisto, onde colocar eles,
da maneira como eu tinha pensado de inicio, seria implementado isto dentro do PrevalentSystem do usuário (acho que é este o nome da classe, não mexi muito com o prevayler ainda :slight_smile:

agora pior que isto, imagina só se o cara resolve utilizar por exemplo Ognl para pesquisas na arvore de objetos, como fazer o lazzy loading para isto, ja que o Ognl vai varrer todos provavelmente??

louds

O esforço para implementar isso de forma eficiente me parece 10x maior que implementar 1 container EJB 2.1.

Uma forma de solucionar esse problema é se for feita uma separação dos dados do business logic. Algo semelhante ao CMP 2.0, mas sem todo o clutter e engeçamento com EJB.

Algo como vc definir suas classes como sem abstratas e todo acesso aos dados ser feito via getters/mutators.

Dai fica muito mais simples implementar politicas de passivation, lazy loading, smart collections, object handles, etc. Se bem que object handles é possivel implementar legal com 1 pouco de hacking em subclasses dos ObjectStreams.

saoj

Bom, já vi que a coisa é complexa ao extremo, mas tentando ser objetivo e simplista:

Não sei se estou viajando, mas minha idéia seria mais ou menos assim: Cada objeto poderia ser colocado num estado passivated de forma que ele só possuiria a sua chave primária e nenhum dado a mais. Então vamos supor que a gente tivesse um Map com 2 milhões de objetos User. Alguns desses Users poderiam estar passivated e isso seria transparente para qualquer busca, pois a nossa Map estaria completinha, ou seja, com os 2 milhoes de Users. Agora se alguém quiser fazer um fetch no usuário Sergio e esse usuário estiver passivated, ele vai ter que esperar a deserialização do disco.

Os LRU tomariam realmente mais espaço, mas talvez somando tudo sairíamos em vantagem, pois numa tabela com 2 milhões de usuários, quantos estão realmente sendo acessados ???

Não entendi o seu conceito de Proxy, poderia explicar melhor? Esse proxy seria a versão passivated do objeto ???

A versão passivated dos objetos resolveria o problema das iterações.

pcalcado

Kct, eu postei uma resposta na riojug de manhã e ainda não chegou :x
Vamos ver se consigo lembrar o que estava escrito…

Meu ponto de vista é o seguinte:

  1. é necessário
  2. é complexo pra kct, até alguém colocar um ovo em pé :idea: e deixar a gente com cara de babaca :roll:
  3. A performance [falando especificamente da mensagem do Elizário, an RioJug] não iria cair se só fosse utilizado quando houvesse risco de estouro de memória

Considerando que precisamos manter a estrutura de POJOs:

  1. como colocar um objeto em memória auxiliar sem saber quanta gente está “apontando” para ele?
  2. Ainda que saibamos, como colocar um proxy no local, falando especificamente em gerência de memória, ou como substituir todas as referências, que podem ser privadas?
  3. Ainda que consigamos colocar um proxy, este proxy estende o objeto serializado [afinal, deveria prover uma interface igual aos clientes do serializado], se sim, e se tivermos uma classe final?
  4. como saber se um objeto foi lido recentemente ou não? Poderíamos ter um objeto quase imutável, talvez que forneça uns parâmetros tipo “índice da taxa de juros COPOM”, que são modificados uma vez a cada mês/ano/década/nunca, mas que são cosntantemente acessados e precisam estar disponíveis. Limitar o acesso via algum wrapper ou através de DAOs, Commands, transactions, whatever iria limitar e muito nossas possibildiade sno uso de Prevalência

Situação em que seria necessário um passivate, siga os passos:

  1. Você tem um site.
  2. Este site registra um pequeno objeto com o IP e hora de cada visita.
  3. Você usa prevalência.
  4. Seu site é bom rpa cacete e aparece no slashdot.
  5. Sua JVM morre

Se a droga do mail chegar eu colo aqui, mas creio que era basicamente isso…

saoj

Não poderíamos ignorar isso? Se eu dei um passivate num objeto e tem um cliente com referencia pra ele, azar. O passivate não vai liberar nenhuma memória, e o cliente pode continuar usando o objeto normalmente. As chances disso acontecer seriam baixas, pois se há clientes com referencia para o objeto, isso significa que ele foi acessado recentemente e provavelmente não estará elegível a passivação.

Minha idéia não é colocar um proxy, mas uma versão passivated do objeto que vai possuir apenas a chave primária e mais nenhum campo.

Não escreva nenhum objeto final, do mesmo jeito que vc não pode escrever nenhum objeto não serialized.

Teríamos que ter um timestamp lastAccessTime

Essa situação é muito interessante !!! E acho que a única solução é:
Para coisas que crescem indefinidamente, como um log de acesso, vc precisa rotacionar a coisa. Não tem jeito !!! Esse log precisa ter um tamanho máximo !!! Esse problema tb acontece com um banco de dados relacional e com o log do Apache.

cv1

Nao vou me dar ao trabalho de quotar as referencias da conversa. Sim, eu sou um preguicoso maldito. Xinguem! :smiley:

Bom, seguinte… sobre a historia de “passivacao”… a gente ja pode comecar abolindo essa palavra, ja que ela traz muitas memorias ruins do pessoal que mexe(ia) com EJB :smiley:

A sugestao do Sergio de colocar uma versao do objeto que so tem chave primaria… bom, pode parar por ai… onde ja se viu objeto com chave primaria? :cry: Se voce vai obrigar o seu sistema prevalente a ter IDs nos objetos, pode ter certeza que o purismo OO foi por agua abaixo :smiley:

Pra trabalhar sem o uso de chaves primarias, e pra fazer o lance da “passivacao” da forma mais simples possivel, é só usar um dynamic proxy que contém uma weak reference pro objeto. Se a JVM precisar coletar a memoria da weakref, beleza… a referencia que o proxy tem vai, de repente, ficar null - e ele precisar do objeto de novo, é “só” buscar no disco. Só entre aspas, pq, como eu mencionei acima, fazer isso de forma performática eh bem chato.

PS: notem que eu estou falando de dynamic proxies. Podem esquecer essa historia de criar classes abstratas, ou de limitar classes final. java.lang.reflect.Proxy na cabeca, meu povo :smiley: - e, se vcs estiverem “moderninhos” hoje, a gente pode comecar a falar de CGLIB :smiley:

Sobre o exemplo do Phillip: concordo que os logs teriam que ser rotacionados, mas vamos imaginar que por algum motivo a gente nao pode (afinal, ta cheio de sistema por ai onde nao da pra rotacionar dados, e ponto). :wink:

pcalcado

Não poderíamos ignorar isso? Se eu dei um passivate num objeto e tem um cliente com referencia pra ele, azar. O passivate não vai liberar nenhuma memória, e o cliente pode continuar usando o objeto normalmente. As chances disso acontecer seriam baixas, pois se há clientes com referencia para o objeto, isso significa que ele foi acessado recentemente e provavelmente não estará elegível a passivação.

E como eu saberia que a classe foi acessada? E a liberdade do OO? [mais sobre isso abaixo]

Bom, o cv falou sobre isso, então vou me ater a dizer que isto me lembra este post aqui: http://www.jroller.com/comments/pcalcado/Weblog/can_prevalence_resist_bad_design

Uma vez eu li em algum lugar que utilizar qualquer coisa final era ruim. eu concordei e me perguntei porque raios existe a droga do final, se é só rpa constantes, sei lá. Aí eu li o Effective Java e percebi que realmente tudo tem seu lugar. Não vou comentar o livro aqui, a Bani tem um ótimo resuminho no blog dela, ams recomendo que realmente leiam, muito bom, mesmo. O que importa é que: sim, existem necessidades de se implemetar algo final, principalmente num projeto bem feito. Talvez objetos final possam ter que ser serializados “na mão”, mas algum jeito tem que ter!

I see dead POJOs.


Essa situação é muito interessante !!! E acho que a única solução é:
Para coisas que crescem indefinidamente, como um log de acesso, vc precisa rotacionar a coisa. Não tem jeito !!! Esse log precisa ter um tamanho máximo !!! Esse problema tb acontece com um banco de dados relacional e com o log do Apache.

Eu pensei neste exemplo a primeira vez há algum tempo, quando o wiki do Prevayler caiu. É só um exemplo, mas pense: você tem um site com mil acessos dia, você limpa sua “base de dados” de acessos todos os dias [tipo os referres do JRoller], aidna que a taxa de acessos triplique, seus vários GB de memória iriam aguantera fácil…só que você não pdoe prever a demanda de um dia assim. Ok, pdoe não acontecer nunca, mas se estamsof alando de alta disponibildiade e missão crítica, temos que pensar neste tipo de tragédia.

cv, vou dar uma olhada na Proxy, depois comento teu post.

E agora, com licença que minha linha é discada [não riam muito alto, por favor!] se tiver alguém acordado para comentar isso, talvez eu ainda leia.

[]s, galera

louds

É longe de ser simples assim. Vale lembrar que vcs vão estar Serializando Objetos lotados de DP e References, isso é 1 dor de cabeça para fazer direito.

A chave para isso ser eficiente é serializar somente o POJO e os seus VOs, referencias para outros POJO’s persistences devem ser salvas da mesma forma.

Outra coisa que vcs esquecem é que usando DP ou CGLIB sempre existe o problema de reference leaking.

saoj

Tudo bem! Chave primária é coisa de banco de dados mesmo, mas não acredito ser esse um motivo suficiente para descartarmos a idéia. A tal da chave primária seria o ID único do objeto. Se estamos falando de usuários, cada um terá que ter obrigatoriamente um identificador único, que em banco de dados eles chamam de chave primária. A idéia é quando encontrarmos um objeto passivado (ou swapado, ou removido, ou desativado) e tivermos a necessidade de acessá-lo, teremos que trazer ele de volta do disco, e uma chave primária (desculpe, um identificador único) vai ser bastante útil pra isso.

Dei uma olhada nos Proxies, e apesar de nunca te-los utilizado na prática, entendi que eles retornam um novo objeto com a mesma interface do objeto proxiado. Se vc puder explicar qual seria a vantagem de um proxy+weak references aqui seria legal. Eu continuo achando que a idéia mais simples, apesar de provavelmente não a mais performática, seria carregar o objeto do disco no momento que alguém tentar acessá-lo.

Como vc controlaria os objetos que estão sendo passivados via Weak Reference? Não seria uma decisão do GC? Não seria melhor e bem mais simples controlar isso na mão com lastAccessTime ?

Estou apenas humildemente trocando idéias. Se aparecer um motivo sólido não vejo problema em abandonar as idéias acima.

Um abraço,

Sergio Oliveira
http://www.smartjava.com.br/
http://space4j.dev.java.net/

cv1

Hmm… bateu uma duvida agora: como vc imagina ser notificado de que o sistema esta querendo acessar um objeto qualquer?

A minha ideia de usar proxies é exatamente essa: voce pode fazer esse tratamento no proxy, e o proxy delega todo e qualquer acesso ao objeto “real”, entao ele tem controle sobre essas notificacoes. :smiley:

duardor

Vixi
Conversa de gente grande!
Vou meter meu humilde dedo no meio…
cv, esse proxy delega as chamadas ao objeto real… mas caso este objeto esteja serializado , o q acontece??? Como ele traz o objeto do disco? Onde ele procura???

Abraços

pcalcado

“cv”:

Hmm… bateu uma duvida agora: como vc imagina ser notificado de que o sistema esta querendo acessar um objeto qualquer?

Este é o ponto. Não tem como, ao meu ver, sem substituir o conteúdo em memória por um proxy [falando, por enquanto do design pattern, não necessariamente de reflection] ou sacrificar a simplicidade obrigando que o objeto persistido implemente ou estenda algo :frowning:

saoj

O papo está ótimo. Vejam o excelente email do Phillip e meus comentários:

Fala Phillip !!!

Concordo com muitas coisas que vc falou abaixo, principalmente com o fim da liberdade de acessar os objetos diretamente.

Estou tentando ser simplista, pois já vi que o assunto abre margem para muitas complexidades, e não tenho ambições de fazer um JBoss de uma hora pra outra. :slight_smile:

Não é difícil imaginar um site com 3 milhões de cadastros. Para cada cadastro, vc tem um objeto User. Dependendo da quantidade de informações dos seus usuários, 3 milhões de objetos User já serão suficiente para estourar sua RAM.

O problema da liberdade a meu ver é:

Vc tem um Map users, e quando vc faz um users.get(new Integer(user_id)), vc pode receber um objeto passivado, ou seja, um objeto que não está em memória. Aí fudeu, o seu cliente vai ter que fazer algo do tipo:

if (myuser.isPassivated()) { ou if (myuser instanceof UserPassivated) {

myuser = getFromDisk(user_id);

}

Obrigar o cliente a fazer isso seria forçar demais a barra.

MAS…

Uma solução simplista não poderia ser implementar um Map com essa funcionalidade por trás de forma que quando vc dá um get vc vai receber o objeto de uma maneira ou de outra ???

Apenas idéias soltas. Aguardo comentários !!!

[]'s

Sergio Oliveira

duardor

Vc tah querendo colocar isso por exemplo, na implementacao do get do Map “implementado por trás”???

Sei lá, é como o pcalcado disse… o negocio de instanceof UserPassivated nao me agrada…

Kra, comecou a me dar umas viagens aki agora envolvendo AOP…
:twisted:
Vou tentar formular umas idéias (doidas) e posto aki…

Abraços

saoj

Teremos que pagar algum preço em prol da simplicidade. O desafio seria codificar uma coisa o menos dolorosa possível para quem depois vai estar escrevendo os POJOs. Se eu começar a explicar tudo isso para o pobre programador escrevendo os POJOs, o cara vai debandar na hora. :slight_smile:

Teria que ser algo mais ou menos assim:

“Se quer que seus POJOs sejam passivados, coloque eles nesse Map aqui: PassivationMap” e crie um objeto para representar o identificador único do seu POJO. E esqueça isso…" :slight_smile:

Mais ou menos como o cluster do Space4J. :slight_smile:

[]'s

Sergio

cv1

Acho mais facil exemplificar com codigo duma vez...

public class MeuProxyFeliz implements InvocationHandler {

    private static long lastGlobalID = 0;

    private final WeakReference weakRef;

    private final long id;

    public MeuProxyFeliz(Object realObject) {
        this.weakRef = new WeakReference(realObject);
        this.id = lastGlobalID++;
    }

    /**
     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
     *      java.lang.reflect.Method, java.lang.Object[])
     */
    public Object invoke(Object ignored, Method method, Object[] args) throws Throwable {
        Object proxy = weakRef.get();
        if (null == proxy) {
            // deserializa o bicho!
            
        } else if (descobreSeEuPrecisoSalvarEsteObjeto(id)) {
            // serializa o objeto!
        }

        return method.invoke(proxy, args);
    }
}
duardor

“saoj”:
“Duardor”:

Sei lá, é como o pcalcado disse… o negocio de instanceof UserPassivated nao me agrada…

Teremos que pagar algum preço em prol da simplicidade. O desafio seria codificar uma coisa o menos dolorosa possível para quem depois vai estar escrevendo os POJOs. Se eu começar a explicar tudo isso para o pobre programador escrevendo os POJOs, o cara vai debandar na hora. :slight_smile:

Teria que ser algo mais ou menos assim:

“Se quer que seus POJOs sejam passivados, coloque eles nesse Map aqui: PassivationMap” e crie um objeto para representar o identificador único do seu POJO. E esqueça isso…" :slight_smile:

Mais ou menos como o cluster do Space4J. :slight_smile:

[]'s

Sergio

Será que não têm algo mais simples e que mantenha TOTALMENTE a simplicidade OO???

Thinking…

duardor
"cv":
Acho mais facil exemplificar com codigo duma vez...
public class MeuProxyFeliz implements InvocationHandler {

    private static long lastGlobalID = 0;

    private final WeakReference weakRef;

    private final long id;

    public MeuProxyFeliz(Object realObject) {
        this.weakRef = new WeakReference(realObject);
        this.id = lastGlobalID++;
    }

    /**
     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
     *      java.lang.reflect.Method, java.lang.Object[])
     */
    public Object invoke(Object ignored, Method method, Object[] args) throws Throwable {
        Object proxy = weakRef.get();
        if (null == proxy) {
            // deserializa o bicho!
            
        } else if (descobreSeEuPrecisoSalvarEsteObjeto(id)) {
            // serializa o objeto!
        }

        return method.invoke(proxy, args);
    }
}

Um proxy pra cada objeto???

cv1

Sim… pesado, eu sei, mas ao menos ainda estamos no campo do “possivel” :smiley:

duardor

Pergunta sobre o codigo
Kd o fonte da classe org.space4j.implementation.CommandExecuter???

pcalcado

:x :x :x Putz, eu fico muito p da vida com isso, semrpe que mando um mail grande pra riojug, recebo a resposta antes do e-mail. Nem lembrava o que tinha nele! :x :x :x

Bom, vamos lá. A GoF define o Pattern Proxy [página 198 doi livro em português, para que como eu não tem cartão internacional e comprou na ciência moderna :stuck_out_tongue: ], que serve extamaente para esse uso. O exemplo [muito bom, aliás] dado na descrição é um editor gráfico que rpecisa trabalhar com uma figura muito pesada, que demora para carregar. em vez dele ficar esperando o troço ser finalmente carregado para deixar o usuário brincar com o programa, ele cria um objeto que possui a mesma interface que a figura teria [por exemplo: você pode mudar ele de lugar, apagar, etc.] enquanto a imagem carrega, incluindo todos os atributos do objeto que são “visíveis” [tipo altura e largura da imagem]. A gente vê muito isso [eu, pelo menos, já que tenho linha discada :stuck_out_tongue: ] em browsers, quando carregam figuras. Creio que o Dynamic Proxy que o cv fala, da Reflection, tenha a ver com este padrão de projeto.

Supondo que com a reflection ou sei lá o que consigamos substituir o trecho em memória ocupado pelo objeto [considerando que seria muito mais simples fazer isso do que substituir todas a infinitas referências que um objeto pode ter] por um proxy muito mais magro, este proxy, quando ativado por alguém que mantinha referência ao objeto passivado, apenas chama o objeto real em disco, o coloca em seu próprio lugar e chama a mesma operação neste objeto, devolvendo a memória ao estando de antes da passivação. Pro cliente, seria transparente.

O problema é criar este proxy. Reflection, se funcionar mesmo [sei que prometi, mas ainda não li nada sobre o proxy :oops: ] poderia até ter uma lerdeza, mas a idéia aqui não é guardar objetos em disco a todo instante [como acho que alguns estão pensando, aqui e no JUG], mas sim utilizar em caso emergencial, para que sua aplicação não pare por falta de memória, então não sei se seria um problema tão grande, apesar da lerdeza reflection+serialization se bem considerável…

Não vejo muita fuga além de um agente do sistema de prevalência substituindo objetos ociosos por proxys quando o bicho pegar, mas…

Como vamos saber se um objeto é muito acessado, sem fazer ele implementar nem estender nada?

  1. Utilizar DAO para ler a classe, assim saberíamos quando alguém requisitasse uma classe da persistência no primeiro acesso, ams quem garante que o cara não vai guardar uma referência para esta classe nele mesmo e mandar a gente se danar, nunca mais chamando o DAO rpa nada?

  2. Agrupar os objetos persitidos em estruturas mínimas possíveis, contendo um grupo de objetos correlatos. Passivar toda a estrutura de uma vez, talvez utilizando a opção 1) para monitoria. Assim, teríamos os mesmos problemas, mas creio que a taxa de “passivação errada” seria menor, porque a tendência é que um objeto referenciado a outro seja chamado quando este for chamado, logo se mantivermos o grupo de “amiguinhos” do objeto X na memória, se rpecisarmos de algum deles quando chamarmos X , temos certeza que estarão lá. Uhm…isto está muito imaturo e confuso…

Bem, considerando o primeiro desfafio, de colocar um proxy substituindo o objeto original no endereço de memória deste, resolvido, como monitorar as consultas sem fazer com qeu o cliente tenha que se improtar se está utilizando o modelo de passivação do Space4J versão 2.5 ou o Prevayler 3.4 :?: :?: :?:

Ai meu são tanenbaum…

duardor

Sim… pesado, eu sei, mas ao menos ainda estamos no campo do “possivel” :D

Ok
Na situacao hipotética (bem hipotética mesmo) que tenhamos MUITOOOSSS proxys de modo que apenas estes encham a memória, q poderemos fazer???
Proxys de proxys???

Abraços

saoj

“duardor”:
Pergunta sobre o codigo
Kd o fonte da classe org.space4j.implementation.CommandExecuter???

CommandExecuter não tem !!! :frowning:

O que temos é um Command, que representa uma alteração no Space e que é executado por um Space4J.

Vc está olhando em http://space4j.dev.java.net/

O que procuras ?

duardor

Assim, não sei se é muita viagem, falando em AOP, mas poderíamos fazer q todos que a todos os proxys fossem integrados um aspecto q faria o papel do dao… mas eu ainda não to concordando com esse negocio de um proxy pra cada objeto…

PS: Discussão muito boa!

Abraços

duardor

“saoj”:
“duardor”:
Pergunta sobre o codigo
Kd o fonte da classe org.space4j.implementation.CommandExecuter???

CommandExecuter não tem !!! :frowning:

O que temos é um Command, que representa uma alteração no Space e que é executado por um Space4J.

Vc está olhando em http://space4j.dev.java.net/

O que procuras ?


ueh
Peguei o ccódigo e têm apenas a classe CommandExceuter
???
por isso não entendi q diasbos é ela!

cv1

Nao eh possivel substituir nada na memoria. Quem gerencia isso eh a JVM, e a gente nao quer mexer nisso. Ou seja, todo o seu post foi pras cucuias - desculpe por trazer as más notícias :smiley:

Outra: se vc estiver usando dynamic proxies (reflection ou cglib), ou vc fala com o proxy, ou vc fala com o objeto. Ou seja, ou voce faz com que toda a criacao de objetos “sensiveis” no sistema passe por uma factory que te devolve o proxy no lugar, ou voce tem todos os problemas que o louds mencionou, e mais alguns. Alias, tudo que o louds falou continua valendo: abusar de dynamic proxies desse jeito requer MUITO cuidado.

duardor

Sim… pesado, eu sei, mas ao menos ainda estamos no campo do “possivel” :D

Ok
Na situacao hipotética (bem hipotética mesmo) que tenhamos MUITOOOSSS proxys de modo que apenas estes encham a memória, q poderemos fazer???
Proxys de proxys???

Abraços

Perae
Deixa eu me explicar direito …
Proxies para conjuntos de Proxies (credo, isto tah me cheirando indexação de BD)
:frowning:

Abraços

pcalcado

“duardor”:

Na situacao hipotética (bem hipotética mesmo) que tenhamos MUITOOOSSS proxys de modo que apenas estes encham a memória, q poderemos fazer???
Proxys de proxys???

Um…de repente vc precisa tirar 1 ou dois dos hipotéticas, se estamos falando de servidores robustos [ou de efeito slashdot], não temos muito limites para esbarrar…

Bem, neste caso acho que realmente o negócio é jogar a toalha, rebootar o servidor e resgatar a última réplica enquanto manda o boy ir comprar mais memória! Acho que para chegar aqui, o problema tá na arquitetura de infra-estrutura, de repente o cara quis economizar e não uso um cluster, prevalência é lindiu, maraviliosiu, mas não é magikiu. :smiley:

saoj

“duardor”:
“saoj”:
“duardor”:
Pergunta sobre o codigo
Kd o fonte da classe org.space4j.implementation.CommandExecuter???

CommandExecuter não tem !!! :frowning:

O que temos é um Command, que representa uma alteração no Space e que é executado por um Space4J.

Vc está olhando em http://space4j.dev.java.net/

O que procuras ?


ueh
Peguei o ccódigo e têm apenas a classe CommandExceuter
???
por isso não entendi q diasbos é ela!

De que código vc está falando ??? Pra não atrapalhar a discussão aqui, me manda isso por email: [email removido]

[]'s

Sergio

cv1

…mas… e na situacao (tambem hipotetica) de cair uma bomba nuclear no datacenter? E se os vikings invadirem o predio? E se…?

MEEEEEEENOS, gente, mEEEEEEEEEEnos. :smiley:

cv1

Sim, fodeu - e deixe-me reiterar isso: um objeto NAO EXISTE se ele estiver fora da memoria. É impossivel determinar qual o estado de um objeto (ou seja, quais os dados que ele continha) se ele nao estiver na memoria, ou se vc nao copiar esses dados pra outro objeto. Eh uma limitacao simples, mas que se vc prestar atencao, muda bastante o rumo dessa conversa (que já tá ficando sem pé nem cabeça…)

pcalcado

Era o que eu temia, droga de graal do Proxy foi pro kct. Infelizmente, que vai jogar a toalha sou eu: se não tem como substituir um objeto por outro em memória de jeito nenhum, não dá pra substituir infinitas referências a um objeto [a droga da passagem por valores e não referência!], de que adianta eu criar um proxy no endereço 939393 se o objeto que instanciei a três dias vai procurar em 23323 ? Se não rola nenhuma plaquinha pra indicar “mudamos”, já era.

Pelo visto, o jeito é a própria aplicação ter como selecionar um grupo de objetos e jogar eles na vala, ops, no disco. Legal, pena que isso quebra uma camada…uhm… alguém falou em BMP? damn

ai, ai, são knuth…

duardor

Sim, fodeu - e deixe-me reiterar isso: um objeto NAO EXISTE se ele estiver fora da memoria. É impossivel determinar qual o estado de um objeto (ou seja, quais os dados que ele continha) se ele nao estiver na memoria, ou se vc nao copiar esses dados pra outro objeto. Eh uma limitacao simples, mas que se vc prestar atencao, muda bastante o rumo dessa conversa (que já tá ficando sem pé nem cabeça…)
Dae cv, se isso for verdade absoluta essa conversa jah nao tem pé nem cabeca a muito tempo…
Mas o caso aki é: o objeto NÃO EXISTE em memória mas já existiu (já foi criado em algum momento ueh) mas seu estado está serializado em disco!
To errado?

saoj

Sim, fodeu - e deixe-me reiterar isso: um objeto NAO EXISTE se ele estiver fora da memoria. É impossivel determinar qual o estado de um objeto (ou seja, quais os dados que ele continha) se ele nao estiver na memoria, ou se vc nao copiar esses dados pra outro objeto. Eh uma limitacao simples, mas que se vc prestar atencao, muda bastante o rumo dessa conversa (que já tá ficando sem pé nem cabeça…)

Claro CV !!! :smiley: :smiley: :smiley: :smiley:

Receber um objeto que não está na memória seria coisa para paranormal !!! :smiley: :smiley: :smiley: :smiley:

O que eu quiz dizer é:

Receber um objeto qualquer que sinalize que o o objeto em questão não está na memória e precisa ser trazido de volta.

Esse objeto poderia ser o tal do objeto que representa o identificador único do objeto.

if (myuser instanceof UniqueIdentifier) {

myuser=getFromDisc(user_id);

}

Bom, esse papo foi muito legal. Eu vou tentar, sem maiores pretensões, brincar com isso. Os proxies me parecem ser a solução mais correta, mas não a melhor. Por isso vou partir para a minha solução simplista que eu descrevi acima. Se conseguir alguma coisa descente eu aviso a voces.

Um abraço,

Sergio

pcalcado

Sérgio, eu posso estar doido, mas tenho quase certeza que o quê você está querendo fazer é um proxy, pelo menos o comprotamento é o mesmo.

Realmente, creio que só como um serviço, tipo o “console do administrador do sistema”, o cara seleciona determinados objetos [imposto de renda de 1983?] e joga em hd. Eles estão lá, podem ser chamados em necessidade, como page faults em memória, mas enquanto não chega a hora…lazy…lazy zorra nenhuma, amanhã tem trabalho, fui!

[]s

cv1

Sergio, ja que vc vai ter um tempinho pra brincar (olha eu me aproveitando :D) e descubra o que acontece se vc tenta deserializar um objeto que possui uma WeakReference - isso eh bastante importante, se vc for organizar a coisa usando dynamic proxies, do jeito que eu mostrei. :smiley:

louds

Usando qualquer tipo de proxy resolve o problema de fazer lazy-loading do teu objeto. Agora tem outros problemas que também não são triviais: como descobrir quais objetos estão modificados? como lidar com concorrencia? como demaracar transações? Como lidamos com atualizações de schema?

Eu acho que sem muita manipulação de bytecode ou exigindo algum estupor como CMP exige, fica quase inviavel. Usando manipulação de bytecode, boas práticas como somente acessar atributos via getters/setters e acessar coleções pelas suas interfaces me parece viavel.

duardor

“louds”:

Eu acho que sem muita manipulação de bytecode ou exigindo algum estupor como CMP exige, fica quase inviavel. Usando manipulação de bytecode, boas práticas como somente acessar atributos via getters/setters e acessar coleções pelas suas interfaces me parece viavel.

Tipo como alguns feitos por algumas ferramenta AOP???

Abraços

cv1
  1. bom, pode-se tratar toda chamada de metodo como uma modificacao… ja que a gente tah num proxy mesmo, fica facil descobrir isso (isDirty()! yeah! :?)

  2. hmmm… som de uma bigorna de 16 ton caindo na cabeca do cv

  3. o Nanning faz isso, e de um jeito bem legal alias :smiley:

  4. Ue, migracao de schema ja eh um inferno, e vai continuar sendo um inferno, onde ta o problema, se eh que vai ter mais algum sendo introduzido aqui? :smiley:

dukejeffrie

Bom, o meta-freak (eu) tem algo a dizer:

WeakReferences são referências que permanecem enquanto existir alguma referência forte pro mesmo alvo.

Ou seja, se eu tenho dois objetos, A e B, que tem referências prum P:

class A {
    private P p;
    public P getP() { return p;}
  }

  class B {
    private WeakReference wrP;
    public P getP() { return (P) wr.get();}
  }

Posso fazer assim:

A a = new A();
B b = new B();
a.setP(new P());
b.setP(a.getP());
a.setP(null);
assert (b.getP() == null);

O que a gente tá querendo é uma SoftReference, que sobrevive caso o objeto não seja coletado. Ou seja, se o objeto passar pelo gc, e a única ref pra ele for uma SoftReference, ele morre.

Acho que um problema por si só interessante é lidar com a passivação (existe isso?) de objetos, independentemente de eu estar num sistema prevalente ou não.

Um Sistema Prevalente é um sistema que não pode cair. Que não vai cair. Dá pra quebrar assim: é só fazer um grafo de objetos grande demais pra caber na RAM, e um código que passeie comportadamente nele. O pobre do mecanismo de persistência vai ficar o resto da vida serializando proxy pra abrir espaço, deserializando pra acessar, e nunca retorna, e nunca dá exception!

Se a probabilidade de um objeto ser acessado é inversamente proporcional à idade dele, melhor nem passar pelo prevayler, bota em outro lugar! Nada te impede!

Volto a sugerir o Jisp pra isso.

[]s!!

saoj

Consegui algo descente !!! Parece que está funcionando bonito !!! Fiz um PhoneBookPassivation apenas herdando PhoneBook e trocando a Map.

Está totalmente transparente para o usuário !!!

Se vc quiser uma Map que faça por trás dos panos a passivação/ativação dos seus objetos para economizar RAM, tudo que vc tem que fazer é utilizar uma org.space4j.passivation.PassivationMap !!!

Um thread no background da PassivationMap fica checando de tempos em tempos o lastAccessTime dos objetos e se o objeto não é acessado a bastante tempo vai para o disco.

O programador não precisa fazer absolutamente nada, apenas colocar os seus POJOs nessa Map com put e acessá-los com get.

Os gets da PassivationMap são inteligentes para retornar o objeto desejado da memória ou do disco se estiver passivado.

Vc pode até snapshotear essa Map com os objetos Passivados que não tem problema.

Uma dúvida que estava martelando a minha cabeça é, como alterar um objeto passivado através de um comando ??? Mas se vc pensar bem, de que adianta vc alterar esse objeto se vc não colocar ele no seu Map ? Então o seu comando vai ter que dar um get ou um put no PassivationMap, o que vai gerar uma ativação do objeto e o problema está resolvido.

Comandos que não dão get na Map poderiam trazer problemas. Mas ainda não consigo imaginar como eu usaria um comando desses.

Acho que eu estou pensando um pouco database-oriented, como seu eu estivesse fazendo um update no Map (tabela). Mais ou menos assim: se eu quero alterar o usuário sérgio eu vou no map pego ele (get!) e altero.

Em breve coloco o código aqui para ouvir as críticas e sugestões de vcs.

Abraço,

Sergio Oliveria
http://www.smartjava.com.br
http://space4j.dev.java.net/

louds

Voce ta assumindo que NENHUM objeto no sistema alem do teu map mantem referencias pros Objetos dele. certo? Senão isso tem utilidade quaze zero.

ex:

class Opss implements Serializable {
    Object obj;
     public Opss(Map source) {
         obj = source.get("yahoo!");
     }
}

Agora oque acontece se o teu PassivationMap mandar pro disco o objeto referenciado pela classe acima???

saoj

Entendi, mas isso talvez não seja tão ruim assim !!!

Tecnicamente não há problema. Conceitualmente eu passivei a toa o objeto, pois ele vai continuar em memória.

Se as referencias eventualmente sumirem o GC vai terminar o serviço.

Note tb que isso não será muito comum e vai depender do PASSIVATION_TIME, ou seja, do intervalo de tempo que vc vai utilizar para passivar os objetos. Se alguém está com uma referência pra esse objeto, as chances são que ele foi acessado recentemente e não estará elegível a passivação !!!

Faz sentido?

cv1

Perai, Sergio… como “eh soh colocar no map”? Se voce esta colocando o objeto no map, mas mantem outras referencias a ele, ele nao vai ser tirado da memoria nunca - ele pode ateh ir pro disco, mas isso vai ser enfeite, afinal, ele ainda ta na memoria, e o GC nao removeu ele so pq vc colocou ele num map espertinho… como vc resolveu isso? :smiley:

saoj

O louds já tinha levantado essa bola !!! Veja se o que eu respondi mais acima no forum faz sentido?

Abraço,

Sergio

cv1

“saoj”:
Se alguém está com uma referência pra esse objeto, as chances são que ele foi acessado recentemente e não estará elegível a passivação!

Faz sentido?

Hmmm… nao muito… num sistema prevalente, os objetos vivem muito mais - logo, dizer que “se o GC nao conseguiu remover, é pq tem alguém usando” é incorreto :wink:

saoj

“cv”:
“saoj”:
Se alguém está com uma referência pra esse objeto, as chances são que ele foi acessado recentemente e não estará elegível a passivação!

Faz sentido?

Hmmm… nao muito… num sistema prevalente, os objetos vivem muito mais - logo, dizer que “se o GC nao conseguiu remover, é pq tem alguém usando” é incorreto ;)

Hummmm. Acho que vcs podem ter razão. Mas deixa eu insistir só mais um pouquinho. :o Os objetos vivem muito mais em memória, mas isso não quer dizer que eles são acessados muito mais que em qualquer outro sistema.

Um problema que eu acabei de notar foi o seguinte: (f…)

Se um objeto User contem um objeto Account e vc passiva o User, o account vai junto. Aí quando depois vc ativar o User de novo, o Account pode estar inconsistente !!! (f…)

Não é muito natural alguem alterar o Account de um User por fora do User, mas pode acontecer. Para esses casos teríamos que colocar o objeto Account como transient e carregá-lo de novo quando o user for ativado.

Acho que o meu esquema pode funcionar, mas:

  1. Estou começando a colocar a responsabilidade de mais encima do programador. Se ele faz um design mal feito, o sistema de passivação vai se ferrar ou ser inútil.

  2. Estou tentando fazer uma analogia entre Maps e Tabelas de um banco de dados, onde vc faz update, insert e delete. Isso tem prós e contras que ainda não estão claros para mim.

Vou pensar mais sobre isso… Valeu pessoal !!!

louds

Quanto a passivar objetos atoa, não é tão grave quanto a criar 2 copias do mesmo objeto no sistema, esse é o problema que eu apontei…

saoj

Entendi !!! Caiu a ficha !!! Veja o meu post mais acima…

Abraço

pcalcado

Peraí… se toda alteração no objeto persitido deve ser feita pelos COmmands, e eu tenho uma referência à objA, ele só pode ser lido por mim, correto? Quando eu alterar, passo prum Command, este command vai implicitamente despassivar o treco e substituir pelo objeto que eu passei, podendo retornar esta nova referencia.

Tipo:

1)a -> objeto em lugar X

2)coloque o objeto no lugar X em disco

3)como o lugar X é apotnado por A, não é coletado

4)a lê x na boa

5)a modifica x e passa para um command de update

6)o command recebe o x, traz o passivado do disco, coloca num lugar y

7)comand faz as alterações em y, ele fica igual ao objeto em x

8)command retorna y para o objeto a que o havia chamado [esse passo eu que inventei]

9)eventuais outros objetos que estivessem apontando para X se ferram com uma referência desatualizada

Falei alguma besteira grande ou foram só besteiras médias?

saoj

Todos os POJOs que contenham outros POJOs teriam que declará-los como transient para evitar esse problema. Quando o objeto voltar do disco ele pega a versão mais atualizada do sistema.

Assim fica foda mesmo !!! Nesses casos minha solução vai dançar… hehehe

A não ser que eu exija que o programador seja esperto para fazer um design sem furos… :cry:

louds

“saoj”:
Todos os POJOs que contenham outros POJOs teriam que declará-los como transient para evitar esse problema. Quando o objeto voltar do disco ele pega a versão mais atualizada do sistema.

Ou seja, estamos mandando pro vinagre a OO obrigando todos objetos possuirem alguma forma de OID para os objetos que eles referem.

cv1

…nesses casos que sao 99% das aplicacoes, por sinal :smiley:

saoj

“louds”:

Ou seja, estamos mandando pro vinagre a OO obrigando todos objetos possuirem alguma forma de OID para os objetos que eles referem.

Eu tinha resolvido o problema do OID assim:

package org.space4j.passivation;

import java.io.*;

public class PassivatedObj implements Serializable {
    
    private String full_class_name = null;
    private String unique_id = null;
    private String extra_path = null;
    
    public PassivatedObj(Object obj) {
        this.full_class_name = obj.getClass().getName();
        this.unique_id = String.valueOf(obj.hashCode());
        this.extra_path = getExtraPath(unique_id);
    }
    
    public String getFullClassName() {
        return full_class_name;
    }
    
    public String getUniqueIdentifier() {
        return unique_id;
    }
    
    public String getExtraPath() {
        return extra_path;
    }
    
    private String getExtraPath(String s) {
        int x = s.length();
        return s.substring(x - 2, x);
    }
    
}

Quando eu passivava um objeto, eu tirava ele da memória e colocava um PassivatedObj no lugar dele. Pegava um hashCode e utilizava como OID. (Eu sei que o hashCode pode retornar o mesmo valor para dois objetos diferentes, mas o sistema está se protegendo disso. Se isso acontecer ele não passiva o Objeto com hashCode igual.)

Está funcionando bonitinho !!! Se não fosse pelo problema do objeto que contem outro objeto… :cry: :cry: :cry: :cry: :cry:

saoj

Voltamos então para a estaca zero. Tenho um site com 3 milhões de cadastros. Não dá para colocar tudo isso em memória. Desses 3 milhões, 200 mil são ativos. Não há porque não passivar os outros 2 milhões e 800 mil usuários em disco. Ou então esqueço prevalência.

Nesse caso acho que usando o PassivationMap com cuidado dá para solucionar o problema. Talvez os proxies sejam a solução mais segura mesmo. Vou dar uma estudada nesses proxies com weak references.

Abraço a todos !!!

cv1

SoftReferences :wink:

dukejeffrie

Andei pensando nisso ontem…

C já brincou com RMI?? Quando vc tem um objeto remoto, vc tem na verdade um proxy. O proxy sabe:

  1. Transformar uma chamada de método em um comando seriado que ele envia por um socket
  2. Abrir conexão com a máquina de destino.

Minha idéia começou com o problema da deleção: se vc deleta um objeto do sistema prevalente, o que vc faz com as referências?

Um ponto de partida é vc “saber” quando um objeto é uma entidade (se o nome é muito relacional pra vc, use “remoto”) ou não. Quando um obj é entidade, a associação (isto é, as referências) pra ele precisam ser mais espertas que uma ref. java.

Então que tal implementar uma classe que lida com essa ref esperta? Ela pode implementar Observer e se “desconectar” quando um objeto é removido do seu mapa (pra resolver o problema 1). E toda vez que vc dá get(), o que ela faz é ir pro mapa e dar get() pra pegar o objeto.

Um User tem uma ref esperta pra um Account, então o getAccount() do User tb vai, eventualmente, pro mapa.

Vc ainda tem que lidar com os pobres OIDs, mas isso não é tão ruim. O importante é que durante o design, o programador saiba quais classes têm instâncias que vale a pena passivar.

Pode até ser um esqueminha IoC baseado em interfaces (p.e. implements Passivatable). De qq jeito, como vc precisa de proxies, vc acaba precisando de factories. Mas com um pouco de esforço (e CGLIB), dá pra fazer um esquema 100% dinâmico.

bom, se eu tiver tempo, vou ver esse esquema da ref esperta, posto aqui qq coisa que eu encontre. Tô empolgado! : )

[]s

saoj

“dukejeffrie”:
Andei pensando nisso ontem…

C já brincou com RMI?? Quando vc tem um objeto remoto, vc tem na verdade um proxy. O proxy sabe:

  1. Transformar uma chamada de método em um comando seriado que ele envia por um socket
  2. Abrir conexão com a máquina de destino.

Minha idéia começou com o problema da deleção: se vc deleta um objeto do sistema prevalente, o que vc faz com as referências?

Um ponto de partida é vc “saber” quando um objeto é uma entidade (se o nome é muito relacional pra vc, use “remoto”) ou não. Quando um obj é entidade, a associação (isto é, as referências) pra ele precisam ser mais espertas que uma ref. java.

Então que tal implementar uma classe que lida com essa ref esperta? Ela pode implementar Observer e se “desconectar” quando um objeto é removido do seu mapa (pra resolver o problema 1). E toda vez que vc dá get(), o que ela faz é ir pro mapa e dar get() pra pegar o objeto.

Um User tem uma ref esperta pra um Account, então o getAccount() do User tb vai, eventualmente, pro mapa.

Vc ainda tem que lidar com os pobres OIDs, mas isso não é tão ruim. O importante é que durante o design, o programador saiba quais classes têm instâncias que vale a pena passivar.

Pode até ser um esqueminha IoC baseado em interfaces (p.e. implements Passivatable). De qq jeito, como vc precisa de proxies, vc acaba precisando de factories. Mas com um pouco de esforço (e CGLIB), dá pra fazer um esquema 100% dinâmico.

bom, se eu tiver tempo, vou ver esse esquema da ref esperta, posto aqui qq coisa que eu encontre. Tô empolgado! : )

[]s

Acho que a solução é usar proxies mesmo, como o CV falou desde o início. Inclusive na documentação de Soft References está escrito:

O único porém é que vc terá que escrever uma interface para todo objeto que vc queira passivar. Como RMI e EJB.

Então se eu tenho um objeto User, vou ter que fazer:

public interface User {
  public int getId();
  public String getName();
  public Account getAccount();
}

public class UserImpl implements User {
  // a implementacao do objeto em si...
}

public class UserHandler implements InvocationHandler {
// a mágica da soft reference acontece aqui...
// se está passivado ativa aqui !!!!
}

e colocar um método estático getInstance no UserImpl que retorne o proxy:


User u = (User) Proxy.newProxyInstance(User.class.getClassLoader(),

                                  new Class[] {User.class},

                                  new UserHandler(new UserImpl()));
}

O nosso sistema de prevalencia está ficando com cara de EJB, mas se não há outro jeito, fazer o que? Isso tem que ser muito bem explicadinho para o programador, se nao o cara vai debandar. :slight_smile:

Depois tem que ver se dá para serializar direitinho esse proxy no snapshot.

duardor

:cry:

dukejeffrie

“saoj”:
Acho que a solução é usar proxies mesmo, como o CV falou desde o início.
(…)
Depois tem que ver se dá para serializar direitinho esse proxy no snapshot.

Nunca me passou pela cabeça fazer isso sem proxies. O lance é que se o proxy conhece o mapa (i.e. tem uma referencia forte para ele), ele deve ser transiente. Se ele tem que ser transiente, eu preciso encontrar um jeito de conectar de novo o proxy ao mapa. Isto é, eu preciso de uma Facade que saiba me entregar o mapa (Pode ser um “Not a Container”)

Como na API de logging, onde eu faço Logger.getLogger(), posso fazer um método getMap() que chame PassiveMap.getInstance()… daí fica:

// construtor
public SmartReference(Class targetClass) {
   this.targetClass = obj.getClass();
   this.id = null;
}

protected PassiveMap getMap() {
   return PassiveMap.getInstance(targetClass);
}

public PassiveObject get() {
   return getMap().get(this.id);
}

public void set(PassiveObject obj) {
   if (!this.targetClass.isInstance(obj)) {
      throw ClassCastException(...);
   }
   getMap().put(obj.getId(), obj);
}

// no cliente
public class User {
  private SmartReference account;

   public void setAccount(Account c) {
      account.set(c);
   }

   public Account getAccount() {
      return (Account) account.get();
   }
}

Numa futura implementação, dá pra usar CGLIB pra “aspectar” um objeto de forma que ele use uma SmartReference toda vez que ele tiver como membro uma ref a um objeto que implemente PassiveObject.

“saoj”:
O nosso sistema de prevalencia está ficando com cara de EJB, mas se não há outro jeito, fazer o que? Isso tem que ser muito bem explicadinho para o programador, se nao o cara vai debandar. :slight_smile:

Eu ainda digo que devia ser separado… 8)

[]s!

saoj

Vc está falando de java.lang.reflect.Proxy ???

Se estiver vc vai ter que implementar aquele esquema que eu falei acima, isto é, para cada objeto que vc queira passivar vc vai ter que implementar duas interfaces pra ele (User e UserHandler). Não dá para fugir disso.

Mas acho que entendi o que vc quer fazer :slight_smile:

Ao invés de java.lang.reflect.Proxy, vc quer criar um objeto que vai guardar a referencia de uma forma esperta, o tal do SmartReference.

Pô, acho que vc mantou a charada !!! :shocked!:

Algo assim:

public class SmartReference implements Serializable {
    
    private transient PassivationMap map = null;
    private Integer oid = null;
    
    public SmartReference(Map map, Object obj) {
        this.map = map;
        this.oid = new Integer(obj.hasCode());
        set(obj);
    }
    
    public Object get() {
        return map.get(oid);
    }
    
    public void set(Object obj) {
        map.put(oid, obj);
    }
    
    // use isso daqui para iniciar objetos transientes !!!
    // Isso é um hack legal que a Sun fez !!! hehehe
    private void readObject(ObjectInputStream stream)  throws ClassNotFoundException, IOException {
        stream.defaultReadObject();
        // map = .....
        // temos que dar um jeito de voltar com o PassivationMap aqui...
        // deve ter um jeito tranquilo...
    }


    
}

Dessa maneira o proxy (SmartReference) não precisa ter uma referencia forte para o Objeto. O PassivationMap saberá se livrar da referencia quando ele passivar o objeto. (Estou abstraindo o PassivationMap, pois já implementei ele!)

A única exigência é que o Objeto produza um hashCode único, ou seja, o objeto precisa ter um identificar único, como uma chave primária.

Será que matamos o problema ??? O que falta ???

saoj

Implementei um suporte mínimo de passivação no Space4J. Basicamente criei um PassivationMap e um PassivationObj. Tudo que o programador precisa fazer é colocar os seus objetos num PassivationMap que o sistema cuida da passivação pra ele.

PassivationMap: Recebe Object via put e devolve PassivationObj via get. Monitora os PassivationObjs para passivação. Se um PassivationObj não é acessado a mais de N minutos, a PassivationMap passiva ele.

PassivationObj: Protege a referencia do objeto sujeito a passivação, como o SmartReference acima. Possui um timestamp (lastAccessTime) e um filename onde o objeto deverá ser serializado. Expõe o objeto ao mundo via o método get(), que se necessário recupera o objeto do disco.

Notas:

  1. Todo objeto sujeito a passivação precisa ter um oid, que deverá ser retornado pela sua função hashCode e será usado na construção do filename. Normalmente esse oid será o id único da entidade.

  2. Nenhum objeto deve manter referências fortes a um objeto sujeito a passivação, mas sim ao seu PassivationObj, que nada mais é que um Wrapper do objeto.

  3. Não usei SoftReference para ter mais controle sobre as circunstâncias da passivação. Além disso como uma soft reference notifica o mundo exterior que está coletando o objeto da sua referencia ??? Acho que só via o finalize do Objeto, mas aí teríamos que fazer um callback do Objecto para o seu PassivationObj via uma interface. Precisamos ser informados disso para serializar o objeto nesse momento. Deixando o PassivationMap controlar tudo isso fica mais fácil.

O código está em http://space4j.dev.java.net/. Aguardo sugestões, críticas, etc.

[]'s

Sergio

dukejeffrie

Uhuuuuu!!!

Passivation rulis!!

nunca mais bd!

legal, saoj, vou dar uma olhada assim que der pra respirar aqui!!

Tô curioso pra saber como vc carrega o passivation map…

[]s!!

Criado 24 de março de 2004
Ultima resposta 30 de mar. de 2004
Respostas 66
Participantes 7