[cpif] r19 - in trunk: . tests

svn at argo.es svn at argo.es
Mon Apr 23 20:01:43 CEST 2007


Author: jcea
Date: Mon Apr 23 20:01:41 2007
New Revision: 19

Log:
Mas infraestructura.

Un nuevo ejemplo equivalente al anterior, pero usando
la nueva infraestructura.

Corregido un bug en el ejemplo inicial.



Added:
   trunk/tests/ejemplo2.py
      - copied, changed from r18, /trunk/tests/ejemplo1.py
Modified:
   trunk/database.py
   trunk/tests/ejemplo1.py

Modified: trunk/database.py
==============================================================================
--- trunk/database.py	(original)
+++ trunk/database.py	Mon Apr 23 20:01:41 2007
@@ -1,6 +1,11 @@
 # $Id$
 
-VERSION_DB="2007041901"
+
+VERSION_DB="2007042301"
+
+
+def normaliza_nick(nick) :
+  return nick.lower()
 
 def init_database(monitor) :
   @monitor
@@ -36,5 +41,104 @@
     seguimiento_no_leidos["last_msg2hilo"]=BTree()
     root["seguimiento_no_leidos"]=seguimiento_no_leidos
 
+    root["punto_de_lectura_global"]=BTree()
+
   init()
+
+def usuario_add(conn,nick,datos) :
+  from durus.btree import BTree
+  from durus.persistent_dict import PersistentDict
+  import time
+
+  root=conn.get_root()
+  usuarios=root["usuarios"]
+
+  nick_normalizado=normaliza_nick(nick)
+  assert nick_normalizado not in usuarios["usuarios"]
+
+  usuarios["num_usuarios"]+=1
+
+  usuarios["usuarios"][nick_normalizado]=PersistentDict(
+                       {"ultimo mensaje conocido":root["mensajes"]["num_mensajes"],
+                        "punto de lectura no leidos":BTree(),
+                        "punto de lectura":BTree(),
+                        "TS creacion":time.time(),
+                        "TS ultima entrada":0,
+                        "num mensajes":0,
+                        "mensajes":BTree(),
+                        "datos":datos})
+
+def mensaje_add(conn,texto,usuario,hilo=None,titulo=None) :
+  from durus.btree import BTree
+  from durus.persistent_dict import PersistentDict
+  import time
+
+  usuario=normaliza_nick(usuario)
+
+  root=conn.get_root()
+  hilos=root["hilos"]
+  mensajes=root["mensajes"]
+  seguimiento_no_leidos=root["seguimiento_no_leidos"]
+
+  mensaje=PersistentDict(
+             {"texto":texto,
+              "TS":time.time(),
+              "autor":usuario})
+
+  mensajes["num_mensajes"]+=1
+  num_msg=mensajes["num_mensajes"]
+  mensajes["mensajes"][num_msg]=mensaje
+
+  if hilo!=None :
+    h=hilo
+    mensaje["hilo"]=hilo
+    hilo=hilos["hilos"][hilo]
+    last=hilo["mensajes"].get_max_item()[0]
+    del seguimiento_no_leidos["last_msg2hilo"][last]
+  else : # Empezamos un hilo nuevo
+    hilos["num_hilos"]+=1
+    h=hilos["num_hilos"]
+    root["punto_de_lectura_global"][h]=0
+    hilo=PersistentDict()
+    assert titulo
+    hilo=PersistentDict(
+         {"creador":usuario,
+          "TS creacion":time.time(),
+          "titulo":titulo,
+          "num_mensajes":0,
+          "mensajes":BTree()})
+    hilos["hilos"][h]=hilo
+    mensaje["hilo"]=h
+
+  seguimiento_no_leidos["hilo2last_msg"][h]=num_msg
+  seguimiento_no_leidos["last_msg2hilo"][num_msg]=h
+
+  hilo["num_mensajes"]+=1
+  hilo["mensajes"][num_msg]=mensaje
+
+  usuario=root["usuarios"]["usuarios"][usuario]
+  usuario["num mensajes"]+=1
+  usuario["mensajes"][num_msg]=mensaje
+
+def actualiza_no_leidos(conn,usuario) :
+  root=conn.get_root()
+  punto_de_lectura_global=root["punto_de_lectura_global"]
+  usuario=root["usuarios"]["usuarios"][normaliza_nick(usuario)]
+  l=usuario["ultimo mensaje conocido"]
+  posicion_hilos_no_leidos=usuario["punto de lectura no leidos"]
+  posicion_hilos=usuario["punto de lectura"]
+
+  last_msg2hilo=root["seguimiento_no_leidos"]["last_msg2hilo"]
+
+  for last,hilo in last_msg2hilo.items_backward() :
+    if last<=l : # Hemos terminado. Esto sera mas simple en Durus 3.7
+      usuario["ultimo mensaje conocido"]=root["mensajes"]["num_mensajes"]
+      break
+    # Vemos cual es el ultimo leido para ese hilo
+    ultimo=posicion_hilos.get(hilo) # Esta es la optimizacion de hilos que todo el mundo ha leido ya...
+    if not ultimo : ultimo=punto_de_lectura_global[hilo]
+    if ultimo < last : # Este hilo tiene mensajes nuevos...
+      posicion_hilos_no_leidos[hilo]=ultimo # Lo marcamos como pendiente de leer y nos vamos al ultimo que hemos leido
+
+
 

Modified: trunk/tests/ejemplo1.py
==============================================================================
--- trunk/tests/ejemplo1.py	(original)
+++ trunk/tests/ejemplo1.py	Mon Apr 23 20:01:41 2007
@@ -8,6 +8,10 @@
 
 # Modificado para que funcione en nuestro entorno
 
+from logging import disable
+disable(9999)
+
+
 import os
 os.chdir("..")
 import sys
@@ -96,28 +100,27 @@
 from random import randint 
  
 @monitor
-def mete_mensajes(conn) :
+def mete_mensaje(conn,hilo) :
   root=conn.get_root()
-  # Elegimos 100 hilos al azar 
-  hilos=[randint(0,999) for i in xrange(100)] # Insertamos 100 mensajes nuevos en hilos al azar 
-  t=time.time() 
-  for hilo in hilos : # Lo que sigue se puede optimizar bastante, pero ya vuela... 
-    num_msg=root["proximo mensaje"] 
-    root["proximo mensaje"]+=1 
-    last=root["hilo2last_msg"][hilo] 
-    root["hilo2last_msg"][hilo]=num_msg 
-    del root["last_msg2hilo"][last] 
-    root["last_msg2hilo"][num_msg]=hilo 
+  num_msg=root["proximo mensaje"] 
+  root["proximo mensaje"]+=1 
+  last=root["hilo2last_msg"][hilo] 
+  root["hilo2last_msg"][hilo]=num_msg 
+  del root["last_msg2hilo"][last] 
+  root["last_msg2hilo"][num_msg]=hilo 
 
+# Elegimos 100 hilos al azar
+hilos=[randint(0,999) for i in xrange(100)]*10 # Insertamos 1000 mensajes nuevos en hilos al azar
 t=time.time()
-mete_mensajes()
-print "Realizamos %f inserciones por segundo" %(100/(time.time()-t))
+for hilo in hilos :
+  mete_mensaje(hilo)
+print "Realizamos %f inserciones por segundo" %(1000/(time.time()-t))
 
  
  
 # Bien, ahora un usuario quiere ver que hilos no ha leido, y movese al ultimo 
 # mensaje no leido de cada uno de ellos. 
-# Observese que este caso es MUY pesimista, ya que puede haber hasta 100 
+# Observese que este caso es MUY pesimista, ya que puede haber hasta 100
 # hilos con mensajes nuevos, lo que es poco realista. El tiempo REAL 
 # es propocional al numero de hilos actualizados, no al numero de mensajes 
 # posteados. Es decir, si se han actualizado 100 hilos con un unico mensaje 
@@ -127,30 +130,30 @@
 # es enorme. 
 
 @monitor
-def actualiza_usuarios(conn) :
+def actualiza_usuario(conn,usernum) :
   root=conn.get_root()
-  for usernum in xrange(1000) : # Probamos a hacer login de los primeros 1000 usuarios 
-    usuario=root["usuarios"][usernum] 
+  usuario=root["usuarios"][usernum] 
 
 # Lo que sigue es un poco "raro" por una limitacion de la version actual de 
 # durus. En Durus 3.7, actualmente en beta, podremos iterar sobre intervalos abiertos... 
-    l=usuario["ultimo mensaje conocido"] 
-    posicion_hilos_no_leidos=usuario["punto de lectura no leidos"] 
-    posicion_hilos=usuario["punto de lectura"] 
-    punto_de_lectura_global=root["punto de lectura global"] 
-
-    for last,hilo in root["last_msg2hilo"].items_backward() : 
-      if last<l : # Hemos terminado. Esto sera mas simple en Durus 3.7 
-        usuario["ultimo mensaje conocido"]=root["last_msg2hilo"].get_max_item()[0] 
-        break 
-      # Vemos cual es el ultimo leido para ese hilo 
-      ultimo=posicion_hilos.get(hilo,None) # Esta es la optimizacion de hilos que todo el mundo ha leido ya... 
-      if ultimo==None : ultimo=punto_de_lectura_global[hilo] 
-      if ultimo < last : # Este hilo tiene mensajes nuevos... 
-        posicion_hilos_no_leidos[hilo]=ultimo # Lo marcamos como pendiente de leer y nos vamos al ultimo que hemos leido 
+  l=usuario["ultimo mensaje conocido"] 
+  posicion_hilos_no_leidos=usuario["punto de lectura no leidos"] 
+  posicion_hilos=usuario["punto de lectura"] 
+  punto_de_lectura_global=root["punto de lectura global"] 
+
+  for last,hilo in root["last_msg2hilo"].items_backward() : 
+    if last<=l : # Hemos terminado. Esto sera mas simple en Durus 3.7 
+      usuario["ultimo mensaje conocido"]=root["last_msg2hilo"].get_max_item()[0] 
+      break 
+    # Vemos cual es el ultimo leido para ese hilo 
+    ultimo=posicion_hilos.get(hilo) # Esta es la optimizacion de hilos que todo el mundo ha leido ya... 
+    if not ultimo : ultimo=punto_de_lectura_global[hilo] 
+    if ultimo < last : # Este hilo tiene mensajes nuevos... 
+      posicion_hilos_no_leidos[hilo]=ultimo # Lo marcamos como pendiente de leer y nos vamos al ultimo que hemos leido 
 
 t=time.time()
-actualiza_usuarios()
+for usernum in xrange(1000) : # Probamos a hacer login de los primeros 1000 usuarios
+  actualiza_usuario(usernum)
 print "En un caso muy pesimista, tenemos %f actualizaciones de hilos no leidos por segundo" %(1000/(time.time()-t))
 
 

Copied: trunk/tests/ejemplo2.py (from r18, /trunk/tests/ejemplo1.py)
==============================================================================
--- /trunk/tests/ejemplo1.py	(original)
+++ trunk/tests/ejemplo2.py	Mon Apr 23 20:01:41 2007
@@ -8,87 +8,46 @@
 
 # Modificado para que funcione en nuestro entorno
 
+from logging import disable
+disable(9999)
+
 import os
 os.chdir("..")
 import sys
 sys.path.append(".")
 
 
-from durus.btree import BTree 
-from durus.persistent_dict import PersistentDict 
-
 import storage
 dummy,dummy,monitor=storage.storage_and_monitor("db-test",storage=storage.storage_test)
 
-# La numeracion de los mensajes es global. 
-# Lo primero es crear el arbol de actualizacion de hilos 
-# dicho arbol, indexado por numero de mensaje global, nos indica en que 
-# momento se actualizo, por ultima vez, un hilo concreto 
-# 
-# Por otra parte tenemos otro arbol, indexado por hilo, que 
-# nos indica el ultimo mensaje del mismo 
-# 
-# En principio suponemos que cada hilo solo tiene un mensaje, 
-# para inicializar todos los hilos con "algo". 
+import database
 
-hilo2last_msg=BTree() 
-last_msg2hilo=BTree() 
- 
-for i in xrange(1000) : # Hay mil hilos, cada uno con un mensaje. LA NUMERACION ES GLOBAL!!! 
-  hilo2last_msg[i]=i 
-  last_msg2hilo[i]=i 
- 
-# Al principio suponemos que los usuarios estan "al dia". Es decir, para cada 
-# hilos, han leido todos los mensajes. 
- 
-# Cada usuario tiene tres datos: 
-# - El ultimo numero de mensaje que "sabe" que ha entrado en los hilos 
-# - La posicion de lectura en cada hilo 
-# - El ultimo mensaje leido en cada hilo con mensajes nuevos 
-# 
-# OPTIMIZACION: Un hilo leido por TODOS los usuarios 
-# no se mantiene (su posicion) en cada usuario, sino en 
-# una estructura global. Es decir, cuando se quiere ver cual 
-# es el numero del ultimo mensaje leido por un usuario en 
-# un hilo concreto, buscamos la posicion de de dicho hilo 
-# en la estructura privada del usuario. Si ahi no aparece nada, 
-# la buscamos en la estructura global, compartida por todos los 
-# usuarios. Esta es una optimizacion de espacio en disco, ya 
-# que en cada usuario solo se guardaran las posiciones de lectura 
-# en los hilos "vivos", mientras que los hilos muertos 
-# se guardan en la estructura global, compartida por todos los 
-# usuarios. 
-
-# En lo que sigue suponemos que todos los usuarios parten de todos 
-# los mensajes leidos, asi que su posicion estara en una estructura 
-# global que no se muestra. Basicamente, lo que se guarda localmente 
-# en cada usuario es su diferencia personal respecto a esa tabla global. 
- 
-import copy 
-punto_de_lectura_global=copy.deepcopy(hilo2last_msg) 
- 
-usuarios=BTree() 
-for i in xrange(10000) : # 10.000 usuarios 
-  usuarios[i]=PersistentDict({"ultimo mensaje conocido":999, \
-                              "punto de lectura no leidos":BTree(), \
-                              "punto de lectura":BTree()}) 
- 
+database.init_database(monitor)
 
-# Una vez inicializado todo, comprometemos la transaccion 
 @monitor
-def inicializa(conn) :
+def inicializacion(conn) :
   root=conn.get_root()
-  root["usuarios"]=usuarios 
-  root["hilo2last_msg"]=hilo2last_msg 
-  root["last_msg2hilo"]=last_msg2hilo 
-  root["proximo mensaje"]=1000 
-  root["punto de lectura global"]=punto_de_lectura_global 
-  print "Commit inicial..." 
- 
-inicializa()
+  usuarios=root["usuarios"]["usuarios"]
+  for i in xrange(10000) : # 10.000 usuarios
+    i=str(i)
+    database.usuario_add(conn,i,{})
+# Marcamos como "leido hasta aqui"
+    usuarios[i]["ultimo mensaje conocido"]=1000
+
+  for i in xrange(1000) : # 1.000 hilos
+    database.mensaje_add(conn,"prueba",str(i),None,"hilo %d" %i)
+
+# Marcamos todo como leido, para todos
+  punto_de_lectura_global=root["punto_de_lectura_global"]  
+  for i in xrange(1,1001) :
+    punto_de_lectura_global[i]=i
+
+  print "Commit inicial..."
+
+inicializacion()
+
 
 
- 
 # Aqui empieza la chicha. Lo primero que queremos saber es el coste 
 # de insercion de un mensaje nuevo. 
  
@@ -96,61 +55,24 @@
 from random import randint 
  
 @monitor
-def mete_mensajes(conn) :
-  root=conn.get_root()
-  # Elegimos 100 hilos al azar 
-  hilos=[randint(0,999) for i in xrange(100)] # Insertamos 100 mensajes nuevos en hilos al azar 
-  t=time.time() 
-  for hilo in hilos : # Lo que sigue se puede optimizar bastante, pero ya vuela... 
-    num_msg=root["proximo mensaje"] 
-    root["proximo mensaje"]+=1 
-    last=root["hilo2last_msg"][hilo] 
-    root["hilo2last_msg"][hilo]=num_msg 
-    del root["last_msg2hilo"][last] 
-    root["last_msg2hilo"][num_msg]=hilo 
+def mete_mensaje(conn,usuario,hilo,mensaje) :
+  database.mensaje_add(conn,mensaje,usuario,hilo)
 
+hilos=[randint(1,1000) for i in xrange(100)]*10 # Insertamos 1000 mensajes nuevos en 100 hilos al azar
 t=time.time()
-mete_mensajes()
-print "Realizamos %f inserciones por segundo" %(100/(time.time()-t))
+for hilo in hilos :
+  mete_mensaje(str(hilo),hilo,"PRUEBA!!!")
+print "Realizamos %f inserciones por segundo" %(1000/(time.time()-t))
 
  
- 
-# Bien, ahora un usuario quiere ver que hilos no ha leido, y movese al ultimo 
-# mensaje no leido de cada uno de ellos. 
-# Observese que este caso es MUY pesimista, ya que puede haber hasta 100 
-# hilos con mensajes nuevos, lo que es poco realista. El tiempo REAL 
-# es propocional al numero de hilos actualizados, no al numero de mensajes 
-# posteados. Es decir, si se han actualizado 100 hilos con un unico mensaje 
-# mas que en el caso normal de que se hayan actualizado unos pocos hilos, 
-# cada uno de ellos con varios mensajes. 
-# Pero vamos a ser muy pesimistas y suponer que el numero de hilos actualizados 
-# es enorme. 
-
 @monitor
-def actualiza_usuarios(conn) :
-  root=conn.get_root()
-  for usernum in xrange(1000) : # Probamos a hacer login de los primeros 1000 usuarios 
-    usuario=root["usuarios"][usernum] 
-
-# Lo que sigue es un poco "raro" por una limitacion de la version actual de 
-# durus. En Durus 3.7, actualmente en beta, podremos iterar sobre intervalos abiertos... 
-    l=usuario["ultimo mensaje conocido"] 
-    posicion_hilos_no_leidos=usuario["punto de lectura no leidos"] 
-    posicion_hilos=usuario["punto de lectura"] 
-    punto_de_lectura_global=root["punto de lectura global"] 
-
-    for last,hilo in root["last_msg2hilo"].items_backward() : 
-      if last<l : # Hemos terminado. Esto sera mas simple en Durus 3.7 
-        usuario["ultimo mensaje conocido"]=root["last_msg2hilo"].get_max_item()[0] 
-        break 
-      # Vemos cual es el ultimo leido para ese hilo 
-      ultimo=posicion_hilos.get(hilo,None) # Esta es la optimizacion de hilos que todo el mundo ha leido ya... 
-      if ultimo==None : ultimo=punto_de_lectura_global[hilo] 
-      if ultimo < last : # Este hilo tiene mensajes nuevos... 
-        posicion_hilos_no_leidos[hilo]=ultimo # Lo marcamos como pendiente de leer y nos vamos al ultimo que hemos leido 
+def actualiza_usuario(conn,usuario) :
+  database.actualiza_no_leidos(conn,usuario)
 
+usuarios=[str(i) for i in xrange(10)] # Probamos a hacer login de los primeros 1000 usuarios
 t=time.time()
-actualiza_usuarios()
-print "En un caso muy pesimista, tenemos %f actualizaciones de hilos no leidos por segundo" %(1000/(time.time()-t))
+for usernum in usuarios :
+  actualiza_usuario(usernum)
+print "En un caso muy pesimista, tenemos %f actualizaciones de hilos no leidos por segundo" %(10/(time.time()-t))
 
 



More information about the cpif mailing list