]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - doc/informe_2da_entrega.lyx
7c71ab5246c249931be6578ab9df9cb0a0f81c8f
[z.facultad/75.06/emufs.git] / doc / informe_2da_entrega.lyx
1 #LyX 1.3 created this file. For more info see http://www.lyx.org/
2 \lyxformat 221
3 \textclass book
4 \language spanish
5 \inputencoding auto
6 \fontscheme palatino
7 \graphics default
8 \paperfontsize default
9 \spacing single 
10 \papersize a4paper
11 \paperpackage widemarginsa4
12 \use_geometry 0
13 \use_amsmath 0
14 \use_natbib 0
15 \use_numerical_citations 0
16 \paperorientation portrait
17 \secnumdepth 3
18 \tocdepth 3
19 \paragraph_separation indent
20 \defskip medskip
21 \quotes_language english
22 \quotes_times 2
23 \papercolumns 1
24 \papersides 1
25 \paperpagestyle default
26
27 \layout Title
28
29 Organización de Datos (75.06)
30 \newline 
31 Trabajo Práctico
32 \newline 
33 E
34 \begin_inset Formula $\mu$
35 \end_inset 
36
37 FS
38 \layout Author
39
40
41 \series bold 
42 Grupo 11
43 \series default 
44
45 \newline 
46 Nicolás Dimov (77624)
47 \newline 
48 Alan Kennedy (78907)
49 \newline 
50 Leandro Lucarella (77891)
51 \newline 
52 Ricardo Markiewicz (78226)
53 \layout Date
54
55 Segunda Entrega, 31 de Mayo de 2004
56 \layout Standard
57
58
59 \begin_inset LatexCommand \tableofcontents{}
60
61 \end_inset 
62
63
64 \layout Chapter
65
66 Introducción
67 \layout Standard
68
69 En esta entrega el trabajo estuvo concentrado en el manejo de índices para
70  los tipos de archivos implementados en la primer entrega.
71  Los índices se implementaron con:
72 \layout Enumerate
73
74 Árbol B
75 \layout Enumerate
76
77 Árbol B*
78 \layout Enumerate
79
80 Árbol B+
81 \layout Standard
82
83 Además de esto, se pide 3 funciones distintas para estos índices:
84 \layout Enumerate
85
86 Principal
87 \layout Enumerate
88
89 Selectivo
90 \layout Enumerate
91
92 Exhaustivo
93 \layout Standard
94
95 Con la autorización de los ayudantes de la cátedra decidimos que el árbol
96  B+ sólo pueda ser utilizado para índices principal ya que de otra manera
97  no tiene sentido el set secuencial (ver página 
98 \begin_inset LatexCommand \pageref{sub:justificacion}
99
100 \end_inset 
101
102  para una justificación más detallada).
103 \layout Standard
104
105 Finalmente, para obtener listados basados en campos de los cuales no se
106  tiene un índice, se implementó un ordenamiento externo.
107 \layout Standard
108
109 A continuación se presenta una descripción un poco más detallada sobre todas
110  herramientas utilizadas para resolver el trabajo práctico.
111 \layout Section
112
113 Documentación de la API
114 \layout Standard
115
116 Para obtener una documentación de la API más completa, se incluye en formato
117  HTML en el CD-ROM la documentación generado con Doxygen.
118  Esta documentación se encuentra en el directorio 
119 \family typewriter 
120 doc/api/html/index.html
121 \family default 
122 .
123 \layout Chapter
124
125 Estructura común
126 \layout Section
127
128 Tipos
129 \layout Standard
130
131 Se detallan a continuación los tipos de datos definidos y utilizados en
132  las distintas implementaciones que conforman nuestro sistema, siendo el
133  más importante de ellos en esta entrega, la estructura 
134 \family typewriter 
135 INDICE
136 \family default 
137  que actúa como interfaz común para el manejo de cualquier tipo de índice
138  (no importa que tipo de organización física ni de que forma esté implementado,
139  esta estructura proveerá una interfaz abstracta para su manejo).
140 \layout Subsection
141
142 Tipos Comunes
143 \layout Standard
144
145 Se agregaron varios tipos comunes nuevos en esta entrega, en su mayoría
146  relacionados a los índices.
147  Estos tipos son brevemente descriptos a continuación y pueden ser hallados
148  en el archivo 
149 \family typewriter 
150 indices.h
151 \family default 
152 :
153 \layout Itemize
154
155
156 \family typewriter 
157 INDICE_DATO
158 \family default 
159 : usado para representar el conjunto de un ID más su dato.
160 \layout Itemize
161
162
163 \family typewriter 
164 INDICE_TIPO
165 \family default 
166 : indica el tipo de índice (B, B* o B+).
167 \layout Itemize
168
169
170 \family typewriter 
171 INDICE_FUNCION
172 \family default 
173 : indica la función que cumple el índice (principal, selectivo o exhaustivo).
174 \layout Itemize
175
176
177 \family typewriter 
178 INDICE_TIPO_DATO
179 \family default 
180 : indica el tipo de dato que se usa como clave.
181 \layout Itemize
182
183
184 \family typewriter 
185 CLAVE
186 \family default 
187 : representa una clave de un índice.
188 \layout Subsection
189
190 INDICE
191 \layout Standard
192
193
194 \family typewriter 
195 INDICE
196 \family default 
197 \emph on 
198  
199 \emph default 
200 es la estructura principal que encapsula todas las funciones para el manejo
201  de un índice.
202  Posee punteros a funciones que permite utilizar la misma interfaz para
203  distintas implementaciones de árboles.
204  
205 \layout Standard
206
207 Su declaración puede ser observada en el archivo 
208 \family typewriter 
209 indices.h
210 \family default 
211 \series bold 
212  
213 \series default 
214 y cuenta con la siguiente información:
215 \layout Itemize
216
217 Tipo de índice.
218 \layout Itemize
219
220 Tipo de dato que maneja.
221 \layout Itemize
222
223 Función del índice.
224 \layout Itemize
225
226 Información sobre el desplazamiento para ubicar el dato dentro de la estructura
227  a indexar (para poder tener una implementación genérica que sirva para
228  cualquier estructura).
229 \layout Itemize
230
231 Información sobre archivos auxiliares para almacenar cadenas de texto y
232  otras estructuras que eventualmente requiera un índice.
233 \layout Itemize
234
235 Punteros a funciones para:
236 \begin_deeper 
237 \layout Itemize
238
239 Agregar entrada.
240 \layout Itemize
241
242 Borrar entrada.
243 \layout Itemize
244
245 Verificar la existencia de una entrada.
246 \layout Itemize
247
248 Buscar entradas.
249 \layout Itemize
250
251 Obtener clave menor o mayor del índice.
252 \layout Itemize
253
254 Obtener siguiente clave (para recorrido secuencial).
255 \end_deeper 
256 \layout Standard
257
258 Esta estructura define los valores de sus punteros según el tipo de implementaci
259 ón que se desee manejar y esto se realiza a través de la API 
260 \family typewriter 
261 emufs_indice
262 \family default 
263 , implementada en 
264 \family typewriter 
265 indices.h
266 \family default 
267 .
268  Esta API posee funciones para crear y destruir índices, agregarlos y quitarlos
269  de una estructura 
270 \family typewriter 
271 EMUFS
272 \family default 
273 , comparar claves y otras, necesarias para la correcta y completa utilización
274  de los índices a través de la interfaz de 
275 \family typewriter 
276 EMUFS
277 \family default 
278  descripta en la entrega anterior.
279 \layout Subsubsection
280
281 Integración con 
282 \family typewriter 
283 EMUFS
284 \family default 
285 .
286 \layout Standard
287
288 Para integrar la utilización de índices a 
289 \family typewriter 
290 EMUFS
291 \family default 
292  fueron necesarios los siguientes cambios:
293 \layout Paragraph
294
295 Nuevos tipos de archivo.
296 \layout Standard
297
298 Se incluyen dos tipos de archivo nuevos T4 y T5, que representan, respectivament
299 e, un archivo T1 (registros variables, bloques fijos) y un archivo T3 (registros
300  y bloques fijos), ambos organizados como un set secuencial indexado.
301  De esta manera se conserva la interfaz de 
302 \family typewriter 
303 EMUFS
304 \family default 
305  (los punteros a funciones) incluso cuando se debe insertar de forma ordenada,
306  ya que al saber que es T4 o T5 siempre se inserta de forma ordenada.
307 \layout Paragraph
308
309 Puntero a un arreglo de índices.
310 \layout Standard
311
312 Se agrega a la estructura 
313 \family typewriter 
314 EMUFS
315 \family default 
316  un puntero a un arreglo de 
317 \family typewriter 
318 INDICE
319 \family default 
320 , donde el primero es siempre el índice principal.
321 \layout Chapter
322
323 Especificaciones de índices
324 \layout Section
325
326 Indice B
327 \layout Section
328
329 Indice B*
330 \layout Subsection
331
332 Decisiones de diseño
333 \layout Standard
334
335 Una de las pocas decisiones que tuvimos que tomar fue la forma de manejar
336  el nodo raíz.
337  Hay dos formas comunes de hacerlo:
338 \layout Enumerate
339
340 Permitir que el nodo raíz pueda almacenar 2N+1 claves (siendo N el número
341  máximo de claves permitido por nodo).
342 \layout Enumerate
343
344 Hacer que se comporte como un árbol B.
345 \layout Standard
346
347 La primera forma garantiza un mejor aprovechamiento del espacio, ya que
348  se sigue haciendo una partición en 3 nodos hijo con 2/3 de los espacios
349  llenos.
350  El problema que encontramos para hacerlo de esa forma fue que usamos un
351  tamaño de nodo fijo de 512 para poder leer un sector completo del disco
352  y ganar algo de velocidad, por lo que para poder mantener este esquema
353  hubiéramos necesitado de 3 bloques de 512 para poder guardar los 2N+1 claves,
354  desperdiciando 512-tamaño_de_clave espacio en el bloque final y haciendo
355  que cualquier ahorro de espacio en los hijos del nodo raíz difícilmente
356  lo compense.
357 \layout Standard
358
359 Además de esto, el utilizar la segunda forma trae como ventaja la reutilización
360  de código del árbol B, lo que facilita la implementación y el mantenimiento
361  del código.
362 \layout Standard
363
364 Estas son las dos razones principales por las cuales elegimos tratar el
365  nodo raíz como lo hace el árbol B.
366 \layout Section
367
368 Indice B+ Organizacion Secuencial Indexada
369 \layout Subsection
370
371 Decisiones de diseño
372 \layout Standard
373
374 Para la implementación de la organización secuencial indexada de archivos,
375  se ha utilizado un árbol B+, conocido por ser utilizado en términos generales
376  para implementaciones de esta índole.
377 \layout Standard
378
379 Como particularidad el arbol B+, poseerá en sus hojas todas las claves que
380  se hayan insertado en el árbol.
381  No obstante, las mismas no serán todas las claves que se encuentren en
382  el archivo de datos, sino la primer clave de cada bloque de datos, también
383  denominadas 'anclas de bloque'.
384 \layout Standard
385
386 En torno a esta distinción respecto de los demás arboles, el árbol B+ nos
387  indicará a la hora de grabar registros en nuestro archivo de datos con
388  bloques (Organización del TP1, Tipo1 o 3), en que bloque de datos debemos
389  realizar la mencionada inserción.
390  La operativa se detalla más adelante, pero básicamente realizaremos una
391  búsqueda del ancla menor inmediata a la clave del registro que se desea
392  insertar, y esto nos indicará el bloque apropiado (el bloque donde esta
393  el ancla).
394 \layout Standard
395
396 Como resultado concreto de este comportamiento (teniendo en cuenta también
397  el borrado y partición de bloques del .dat), obtendremos un archivo secuencial
398  indexado, en donde los registros se encuentran ordenados a nivel de bloques,
399  esto es, dentro de un bloque dado del archivo de datos, los registros estan
400  ordenados por clave primaria.
401  No obstante, los bloques no estarán necesariamente ordenados, pero igualmente
402  la cantidad de accesos para recorrer el archivo en forma secuencial, se
403  ve minimizada respecto de otras organizaciones, gracias al encadenamiento
404  de las hojas y la posesión de las anclas de bloque, cuya lista resultante
405  del encadenamiento es denominada 
406 \series bold 
407 Sequence Set.
408 \layout Subsubsection
409
410
411 \begin_inset LatexCommand \label{sub:justificacion}
412
413 \end_inset 
414
415 Razones por las cuales el B+ es útil sólo para clave principal.
416 \layout Standard
417
418 El mejor aprovechamiento del Arbol B+ se da en su utilizacion en implementacion
419  ISAM (Indexed Sequential Access Method), en donde se realiza una indexacion
420  parcial de claves, sólo ingresando en el árbol las claves anclas de cada
421  bloque en el archivo de datos.
422  
423 \layout Standard
424
425 Esta aplicación del árbol B+ a ISAM, además de indicarnos donde grabar y
426  donde buscar los registros por identificación primaria, nos asegura el
427  ordenamiento de los registros parcialmente a nivel de bloque (esto es,
428  los registros en un bloque dado, estarán ordenados, pero los bloques no
429  necesariamente).
430  Así pués, recorriendo el Sequence Set del Arbol B+, minimizaremos los saltos
431  de lectura en disco, pues dentro de un bloque indicado por un ancla dada
432  en el Sequence Set, podremos recorrer los registros secuencialmente.
433 \layout Standard
434
435 Visto y considerando que la aplicación más importante a nuestro criterio
436  del Arbol B+, era para la indexacion parcial de claves primarias, y que
437  en caso de utilizarlo para otros índices, el B+ se convertiría simplemente
438  en un B con encadenamiento a nivel de hojas, luego de consultar con los
439  ayudantes, decidimos utilizarlo unicamente para el índice primario, y utilizar
440  el B y B* para los restantes índices y/o el primario.
441  
442 \layout Subsection
443
444 Estructura
445 \layout Standard
446
447 Para comprender mejor la implementación particular que hemos dado al árbol
448  B+, damos una breve reseña de la estructura de un nodo del arbol, la cual
449  es la siguiente:
450 \layout Itemize
451
452 Nivel
453 \layout Itemize
454
455 Cantidad de claves
456 \layout Itemize
457
458 Arreglo de claves
459 \layout Itemize
460
461 Arreglo de hijos
462 \layout Standard
463
464 Esta estructura se encuentra en el archivo 
465 \family typewriter 
466 indice_bplus.h
467 \layout Standard
468
469 Esta organización permite, con la ayuda del árbol, mantener el archivo de
470  datos ordenado por la clave principal.
471 \layout Standard
472
473 Para lograr esto, como fue expuesto anteriormente, el árbol nos indicará
474  donde (en qué bloque) debe insertarse un registro.
475  (ver 3.3.1 Inserción)
476 \layout Standard
477
478 En el caso de una hoja, dado que cada nodo posee un hijo mas que la cantidad
479  de claves, el hijo que sobra será utilizado como referencia al nodo 
480 \begin_inset Quotes eld
481 \end_inset 
482
483 hermano
484 \begin_inset Quotes erd
485 \end_inset 
486
487 , lo cual constituye el 
488 \begin_inset Quotes eld
489 \end_inset 
490
491 set secuencial
492 \begin_inset Quotes erd
493 \end_inset 
494
495  del índice.
496  Para un nodo que no sea hoja el hijo será el número de nodo correspondiente
497  según la clave, es decir, para la clave 
498 \series bold 
499 \emph on 
500
501 \series default 
502 \emph default 
503 el hijo 
504 \series bold 
505 \emph on 
506 n
507 \series default 
508 \emph default 
509  contiene claves menores y el hijo 
510 \series bold 
511 \emph on 
512 n+1
513 \series default 
514 \emph default 
515  contiene las claves mayores.
516  En el caso particular del nivel 1 (index set) el hijo 
517 \series bold 
518 \emph on 
519 n+1
520 \series default 
521 \emph default 
522  (sequence set) contiene las claves mayores o iguales ya que el 
523 \begin_inset Quotes eld
524 \end_inset 
525
526 secuence set
527 \begin_inset Quotes erd
528 \end_inset 
529
530  debe contener todas las claves insertadas, esto produce que exista una
531  repetición de las claves entre el nivel 1 y el 0.
532 \layout Standard
533
534 En nuestro caso hemos implementado un Secuencial Indexado tipo ISAM (Indexed
535  Sequential Access Method) el cual posee en sus hojas las anclas de cada
536  bloque en el archivo de datos, es decir, solo se guardan en los nodos del
537  árbol la menor de las claves de un bloque del archivo de datos, acompañada
538  cada clave por el numero de bloque al cual pertenece.
539 \layout Standard
540
541 Hemos adoptado que la cantidad de claves máxima en un nodo del árbol sea
542  una cantidad impar, ya que esto facilita la elección de la clave que será
543  promovida hacia su nodo padre en caso de que se produzca un overflow en
544  el nodo.
545 \layout Subsection
546
547 Inserción
548 \layout Standard
549
550 Para realizar una inserción en el archivo de datos se debe realizar una
551  consulta en el árbol, la cual nos indicará el número de bloque donde debemos
552  insertar el nuevo registro.
553 \layout Standard
554
555 Las consultas se realizan a través de una estructura INDEX_DAT que posee:
556 \layout Itemize
557
558 Clave
559 \layout Itemize
560
561 Número de Bloque 
562 \layout Standard
563
564 Esta estructura se encuentra en el archivo 
565 \family typewriter 
566 indice_bplus.h
567 \layout Standard
568
569 El modo de uso es el siguiente:
570 \layout Standard
571
572 En primer lugar se carga la clave a insertar en el campo Clave, y en el
573  campo Número de Bloque se almacena un número de bloque válido, mas adelante
574  se explica el por qué.
575 \layout Standard
576
577 Luego se invoca a la función 
578 \family typewriter 
579 int emufs_b_plus_get_bloque(INDICE, INDEX_DAT) 
580 \family default 
581 la cual recibe como parámetro una estructura de índice y un INDEX_DAT para
582  realizar la consulta.
583 \layout Standard
584
585 Esta función recorre recursivamente el árbol y busca una clave mayor inmediata
586  a la enviada, siempre culminando la búsqueda en una hoja.
587  Al encontrar la clave mayor inmediata, el resultado de la búsqueda será
588  la clave anterior en el nodo, pues cada clave en el nodo es un ancla de
589  bloque de datos, de esta manera la clave anterior será menor a la clave
590  enviada, pues las claves en las hojas están ordenadas.
591  
592 \layout Standard
593
594 En este paso pueden suceder dos cosas:
595 \layout Enumerate
596
597 Que exista una clave menor a la enviada.
598 \layout Enumerate
599
600 Que la clave enviada sea menor a todas las claves del árbol.
601 \layout Standard
602
603 En el primer caso, se ha encontrado la clave y se carga la estructura con
604  el hijo de esa clave, que será el número de bloque donde debe insertarse
605  el nuevo registro (por el cual se realizó la consulta), sobreescribiendo
606  el valor que almacenaba al ingresar, y la función retornará código 0 que
607  indica que se ha encontrado un bloque donde insertar.
608 \layout Standard
609
610 En el segundo caso, puede darse que la clave enviada sea menor a todas las
611  claves del árbol, por lo cual no es posible encontrar un ancla de bloque
612  para esa clave.
613  Aquí la función retornará código -1 lo cual indica que no se ha encontrado
614  un bloque donde insertar el registro nuevo, y es por esto que la estructura
615  debe inicializarse con un número de bloque válido antes de realizarse la
616  consulta.De esta manera el árbol indica donde debe insertarse un nuevo registro
617  en el archivo de datos.
618 \layout Standard
619
620 Otro detalle de la inserción es que cuando el árbol indica donde debe insertarse
621  un registro pueden pasar dos cosas nuevamente:
622 \layout Enumerate
623
624 Que el registro quepa en el bloque.
625 \layout Enumerate
626
627 Que el registro no quepa en el bloque.
628 \layout Standard
629
630 El primer caso es trivial y el registro se insertará sin problemas en el
631  bloque indicado.
632 \layout Standard
633
634 En el caso que el registro no quepa en el bloque, se deberán separar los
635  registros del bloque en 2 bloques, en original y uno nuevo, cada uno con
636  la mitad (aproximadamente) de los registros.
637  
638 \layout Standard
639
640 Al partir el bloque el ancla del bloque original no se modificará, pero
641  en el bloque nuevo se crea una nueva anlca de bloque, pues una de las claves
642  pertenecientes a los registros que contiene, será la menor.
643 \layout Standard
644
645 Antes de actualizar el árbol con el ancla nueva, habrá que discriminar en
646  qué bloque se debe insertar el registro nuevo.
647  Para ello se compara la menor de las claves del nuevo bloque con la clave
648  del registro, si la clave del registro es menor que el ancla del nuevo
649  bloque, este debe ir en el bloque original, y se inserta ordenado en él
650  y se le informa al árbol que actualice (inserte) una nueva clave correspondient
651 e al bloque nuevo, sino se inserta en el bloque nuevo de forma ordenada
652  y en este caso cabe la posibilidad de que el nuevo registro posea la clave
653  mas pequeña de todas en el bloque, por ello se lo inserta ordenadamente
654  con ayuda de la función
655 \family typewriter 
656  CLAVE grabar_ordenado_en_bloque(EMUFS *emu, void *ptr, EMUFS_REG_SIZE size,
657  void *bloque, int num_bloque, EMUFS_FREE fs, int *err) 
658 \family default 
659 la cual inserta el registro ordenado por CLAVE y devuelve la menor de las
660  claves del bloque, que se usará para informarle al árbol que inserte una
661  clave nueva junto con el número de bloque, para indexar este bloque.
662 \layout Subsection
663
664 Eliminación
665 \layout Standard
666
667 El proceso de eliminación es bastante similar al de inserción en el sentido
668  que también hay que realizar una consulta en el árbol para obtener el número
669  de bloque al que pertenece una clave.
670  Una vez conocido este número se levanta el bloque correspondiente y se
671  busca secuencialmente el registro que se debe eliminar.
672 \layout Standard
673
674 Si el registro a eliminar fuera el primero del bloque, habrá que modificar
675  el ancla de bloque en el árbol con el ancla que corresponda a la clave
676  del nuevo menor registro, y si el que se elimina fuera el único registro
677  en el bloque habrá que eliminar la clave del árbol.
678 \layout Standard
679
680 En cualquier otro caso, solo se eliminará el registro correspondiente y
681  se justificarán los registros a izquierda.
682 \layout Subsection
683
684 Búsqueda
685 \layout Standard
686
687 El proceso de búsqueda de un registro por su clave de identificación primaria
688  en la Organización Secuencial Indexada, es bastante directa en su entendimiento.
689  Para buscar un registro, acudiremos al árbol B+ con la clave anteriormente
690  mencionada, y obtendremos del mismo, el número de bloque donde se debe
691  encontrar el registro.
692 \layout Standard
693
694 Para obtener dicho número de bloque, el árbol internamente busca el ancla
695  menor inmediata a la clave buscada y luego devuelve el número de bloque
696  de datos donde está dicha ancla (el nro bloque será el dato asociado a
697  la clave ancla, en el árbol), el cual será el bloque potencial donde se
698  encuentre el registro buscado.
699 \layout Standard
700
701 Una desventaja de esta implementación con indexación parcial, es que no
702  sabremos si el registro se encuentra efectivamente en el bloque indicado,
703  hasta no buscarlo dentro del mismo en formal secuencial.
704  Si lo hallamos, daremos por finalizada la búsqueda del registro.
705 \layout Subsection
706
707 Recorrida secuencial de registros
708 \layout Standard
709
710 Una consecuencia importante de la organización secuencial indexada, en este
711  caso implementada a través de un árbol B+ con indexación parcial, es que
712  como mencionamos anteriormente, los registros dentro de un bloque se encuetran
713  ordenados, y si bien los bloques en si pueden no estar ordenados en el
714  archivo de datos, algunos lo estarán, y minimizarán en base a estas característ
715 icas, los tiempos de acceso para una recorrida secuencial de registros.
716 \layout Standard
717
718 Suponiendo que nos encontramos con varios registros cargados en esta organizació
719 n de archivo, y con el correspondiente árbol de indexación primaria B+ en
720  el disco, si se nos pidiera por ejemplo, recorrer los registros de articulos
721  desde el ID_Articulo 40, hasta el ID_Articulo 1406, la operativa será la
722  siguiente:
723 \layout Itemize
724
725 Acudimos al árbol y obtenemos el numero de bloque para el ID_Articulo 40,
726  buscando el ancla menor inmediata y obteniendo el nro de bloque de datos
727  donde se encuentra, siendo este el nro de bloque donde debería estar el
728  artículo de clave ID_Articulo 40.
729 \layout Itemize
730
731 Levantamos el bloque de datos y lo recorremos secuencialmente, pues como
732  dijimos anteriormente, sus registros se encuentran ordenados por la clave
733  de identificación primaria, en este caso ID_Articulo.
734 \layout Itemize
735
736 Cuando ya hayamos procesado todo el bloque, debemos obtener la siguiente
737  ancla a través del árbol y repetir el proceso.
738 \layout Itemize
739
740 NOTA: Cabe desatacar, que todas las anclas estan en las hojas del B+, y
741  por ello las recorremos a nivel hojas a traves del Sequence Set, que gracias
742  a su encadenamiento, nos permite obtener en forma muy directa y efectiva,
743  las anclas de bloque ordenadas en secuencia, y por consiguiente, recorrer
744  el archivo en forma secuencial minimizando accesos.
745 \layout Chapter
746
747 Ordenamiento Externo
748 \layout Section
749
750 Descripción del algoritmo
751 \layout Standard
752
753 Luego de buscar varias alternativas sobre algoritmos de ordenamiento externo,
754  se optó por el siguiente (que resultó una mezcla de las alternativas analizadas
755 ):
756 \layout Enumerate
757
758 Tomar uno a uno los registros del archivo a ordenar e 
759 \emph on 
760 inyectarlos
761 \emph default 
762  en un buffer ordenado hasta llenar el buffer.
763 \layout Enumerate
764
765 Quitar el menor de los valores (
766 \emph on 
767 inyectando
768 \emph default 
769  uno nuevo desde el archivo a ordenar) e insertarlo en un archivo temporal.
770 \layout Enumerate
771
772 Quitar del buffer el mínimo valor mayor al último insertado en el archivo
773  temporal (
774 \emph on 
775 inyectando
776 \emph default 
777  nuevamente un registro obtenido del archivo a ordenar) y se lo inserta
778  en el archivo temporal.
779  De esta forma quedan ordenados los registros en el archivo temporal.
780 \layout Enumerate
781
782 Repetir el paso 3 hasta que se vacíe el buffer o hasta que no haya ningún
783  valor mayor al último insertado en el archivo temporal.
784  Cuando esto suceda se crea un nuevo archivo temporal volviendo al paso
785  2.
786 \layout Standard
787
788 En este punto ya tenemos el buffer vacío y todos los valores del archivo
789  a ordenar repartidos en 1 o más archivos temporales ordenados, sólo queda
790  unir los archivos para volver a un sólo archivo completo y ordenado.
791  El procedimiento es simple:
792 \layout Enumerate
793
794 Obtener el mínimo valor de los archivos temporales e insertarlo en el archivo
795  ordenado de salida.
796 \layout Enumerate
797
798 Repetir 1 hasta agotar los registros de todos los archivos temporales.
799 \layout Standard
800
801 Debe quedar claro que los archivos temporales se comportan como una cola.
802  Es decir que al obtener un registro de un archivo temporal se obtiene el
803  primer registro que se haya insertado (el mínimo por la forma en la que
804  fueron insertados).
805 \layout Subsection
806
807 Ejemplo
808 \layout Standard
809
810 A continuación se presenta un ejemplo para una más fácil comprensión del
811  algoritmo.
812 \layout Standard
813
814 Supongamos que queremos ordenar un archivo con registros de números enteros
815  (el archivo se lee de izquierda a derecha): 9 6 34 2 8 3 12 43 23 4 19
816  21 87 1 16 36 42 65
817 \layout Standard
818
819 Supongamos que disponemos de un buffer capaz de almacenar 3 registros.
820 \layout Paragraph
821
822 Se llena el buffer ordenado
823 \layout Standard
824
825 Se lee 9 del archivo original y se lo inserta en el buffer ordenado.
826  Buffer: 9
827 \layout Standard
828
829 Se lee 6 del archivo original y se lo inserta en el buffer ordenado.
830  Buffer: 6 9
831 \layout Standard
832
833 Se lee 34 del archivo original y se lo inserta en el buffer ordenado.
834  Buffer: 6 9 34
835 \layout Paragraph
836
837 Se crea el archivo temporal ordenado 1
838 \layout Standard
839
840 Se lee el mínimo valor del buffer (6), se lo inserta en el archivo temporal
841  y se carga un nuevo valor del archivo original al buffer (2).
842  Buffer: 2 9 34.
843  Archivo1: 6
844 \layout Standard
845
846 Se lee el mínimo valor del buffer mayor al insertado anteriormente (9),
847  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
848  original al buffer (8).
849  Buffer: 2 8 34.
850  Archivo1: 6 9
851 \layout Standard
852
853 Se lee el mínimo valor del buffer mayor al insertado anteriormente (34),
854  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
855  original al buffer (3).
856  Buffer: 2 3 8.
857  Archivo1: 6 9 34
858 \layout Standard
859
860 No hay más valores en el buffer mayores al último insertado (34), fin del
861  Archivo1.
862 \layout Paragraph
863
864 Se crea el archivo temporal ordenado 2
865 \layout Standard
866
867 Se lee el mínimo valor del buffer (2), se lo inserta en el archivo temporal
868  y se carga un nuevo valor del archivo original al buffer (12).
869  Buffer: 3 8 12.
870  Archivo2: 2
871 \layout Standard
872
873 Se lee el mínimo valor del buffer mayor al insertado anteriormente (3),
874  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
875  original al buffer (43).
876  Buffer: 8 12 43.
877  Archivo2: 2 3
878 \layout Standard
879
880 Se lee el mínimo valor del buffer mayor al insertado anteriormente (8),
881  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
882  original al buffer (23).
883  Buffer: 12 23 43.
884  Archivo2: 2 3 8
885 \layout Standard
886
887 Se lee el mínimo valor del buffer mayor al insertado anteriormente (12),
888  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
889  original al buffer (4).
890  Buffer: 4 23 43.
891  Archivo2: 2 3 8 12
892 \layout Standard
893
894 Se lee el mínimo valor del buffer mayor al insertado anteriormente (23),
895  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
896  original al buffer (19).
897  Buffer: 4 19 43.
898  Archivo2: 2 3 8 12 23
899 \layout Standard
900
901 Se lee el mínimo valor del buffer mayor al insertado anteriormente (43),
902  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
903  original al buffer (21).
904  Buffer: 4 19 21.
905  Archivo2: 2 3 8 12 23 43
906 \layout Standard
907
908 No hay más valores en el buffer mayores al último insertado (43), fin del
909  Archivo2.
910 \layout Paragraph
911
912 Se crea el archivo temporal ordenado 3
913 \layout Standard
914
915 Se repite el proceso anterior.
916  Buffer: 1 16 36.
917  Archivo3: 4 19 21 87
918 \layout Paragraph
919
920 Se crea el archivo temporal ordenado 4
921 \layout Standard
922
923 Se repite el proceso anterior.
924  Buffer: .
925  Archivo4: 1 16 36 42 65
926 \layout Paragraph
927
928 Se mezclan los archivos temporales ordenados obteniendo un archivo completo
929  ordenado
930 \layout Standard
931
932 Se obtiene el menor valor de los archivos temporales ordenados (sólo tenemos
933  que elegir entre el primer valor de cada uno).
934 \layout Standard
935
936 Archivo1: 6 9 34.
937  Archivo2: 2 3 8 12 23 43.
938  Archivo3: 4 19 21 87.
939  Archivo4: 1 16 36 42 65
940 \layout Standard
941
942 Sólo debo comparar y obtener el menor entre 6, 2, 4, y 1.
943  Obtengo el 1, lo saco del archivo temporal y lo agrego al de salida:
944 \layout Standard
945
946 Archivo1: 6 9 34.
947  Archivo2: 2 3 8 12 23 43.
948  Archivo3: 4 19 21 87.
949  Archivo4: 16 36 42 65 Salida: 1
950 \layout Standard
951
952 Repito hasta que no hayan más valores en los archivos temporales:
953 \layout Standard
954
955 Archivo1: 6 9 34.
956  Archivo2: 3 8 12 23 43.
957  Archivo3: 4 19 21 87.
958  Archivo4: 16 36 42 65.
959  Salida: 1 2
960 \layout Standard
961
962 Archivo1: 6 9 34.
963  Archivo2: 8 12 23 43.
964  Archivo3: 4 19 21 87.
965  Archivo4: 16 36 42 65.
966  Salida: 1 2 3
967 \layout Standard
968
969 Archivo1: 6 9 34.
970  Archivo2: 8 12 23 43.
971  Archivo3: 19 21 87.
972  Archivo4: 16 36 42 65.
973  Salida: 1 2 3 4
974 \layout Standard
975
976 Archivo1: 6 9 34.
977  Archivo2: 8 12 23 43.
978  Archivo3: 19 21 87.
979  Archivo4: 16 36 42 65.
980  Salida: 1 2 3 4
981 \layout Standard
982
983 Archivo1: 9 34.
984  Archivo2: 8 12 23 43.
985  Archivo3: 19 21 87.
986  Archivo4: 16 36 42 65.
987  Salida: 1 2 3 4 6
988 \layout Standard
989
990 Archivo1: 9 34.
991  Archivo2: 12 23 43.
992  Archivo3: 19 21 87.
993  Archivo4: 16 36 42 65.
994  Salida: 1 2 3 4 6 8
995 \layout Standard
996
997 Archivo1: 34.
998  Archivo2: 12 23 43.
999  Archivo3: 19 21 87.
1000  Archivo4: 16 36 42 65.
1001  Salida: 1 2 3 4 6 8 9
1002 \layout Standard
1003
1004 Archivo1: 34.
1005  Archivo2: 23 43.
1006  Archivo3: 19 21 87.
1007  Archivo4: 16 36 42 65.
1008  Salida: 1 2 3 4 6 8 9 12
1009 \layout Standard
1010
1011 Archivo1: 34.
1012  Archivo2: 23 43.
1013  Archivo3: 19 21 87.
1014  Archivo4: 36 42 65.
1015  Salida: 1 2 3 4 6 8 9 12 16
1016 \layout Standard
1017
1018 Archivo1: 34.
1019  Archivo2: 23 43.
1020  Archivo3: 21 87.
1021  Archivo4: 36 42 65.
1022  Salida: 1 2 3 4 6 8 9 12 16 19
1023 \layout Standard
1024
1025 Archivo1: 34.
1026  Archivo2: 23 43.
1027  Archivo3: 87.
1028  Archivo4: 36 42 65.
1029  Salida: 1 2 3 4 6 8 9 12 16 19 21
1030 \layout Standard
1031
1032 Archivo1: 34.
1033  Archivo2: 43.
1034  Archivo3: 87.
1035  Archivo4: 36 42 65.
1036  Salida: 1 2 3 4 6 8 9 12 16 19 21 23
1037 \layout Standard
1038
1039 Archivo1:.
1040  Archivo2: 43.
1041  Archivo3: 87.
1042  Archivo4: 36 42 65.
1043  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34
1044 \layout Standard
1045
1046 Archivo1:.
1047  Archivo2: 43.
1048  Archivo3: 87.
1049  Archivo4: 42 65.
1050  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36
1051 \layout Standard
1052
1053 Archivo1:.
1054  Archivo2: 43.
1055  Archivo3: 87.
1056  Archivo4: 65.
1057  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42
1058 \layout Standard
1059
1060 Archivo1:.
1061  Archivo2:.
1062  Archivo3: 87.
1063  Archivo4: 65.
1064  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43
1065 \layout Standard
1066
1067 Archivo1:.
1068  Archivo2:.
1069  Archivo3: 87.
1070  Archivo4:.
1071  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43 65
1072 \layout Standard
1073
1074 Archivo1:.
1075  Archivo2:.
1076  Archivo3:.
1077  Archivo4:.
1078  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43 65 87
1079 \layout Paragraph
1080
1081 Fin
1082 \layout Standard
1083
1084 Finalmente, tengo en el archivo de salida el archivo original ordenado.
1085 \layout Section
1086
1087 Alcance
1088 \layout Standard
1089
1090 El algoritmo de ordenamiento es completamente genérico, ya que recibe un
1091  puntero void como registro, su tamaño (para poder manipularlo sin conocer
1092  su tipo) y una función de comparación, para poder comparar dos registros
1093  (sin saber su tipo) a través de una relación de orden (descripta por dicha
1094  función).
1095 \layout Section
1096
1097 Decisiones de diseño.
1098 \layout Standard
1099
1100 El algoritmo se eligió en base a una serie de razones y cuenta con una serie
1101  de ventajas y desventajas.
1102 \layout Itemize
1103
1104 El algoritmo es simple, tanto teóricamente como para implementar.
1105 \layout Itemize
1106
1107 Tiene la desventaja de que puede llegar a usar muchos archivos temporales
1108  y todos abiertos al mismo tiempo, pero considerando que el sistema operativo
1109  en el que se utiliza suele manejar bien grandes cantidades de archivos
1110  no es una desventaja importante.
1111 \layout Itemize
1112
1113 Al usar un buffer intermedio, se puede controlar muy bien la cantidad de
1114  memoria que utiliza y experimentar con distintos valores para analizar
1115  los resultados.
1116 \layout Itemize
1117
1118 El buffer ordenado se implementó con un árbol binario debido a que tiene
1119  una buena relación entre velocidad de búsqueda y facilidad de implementación.
1120  Al ser el principal determinante de la velocidad los accesos a disco no
1121  se creyó necesario buscar una alternativa más rápida para mantener el buffer
1122  ordenado en memoria, ya que no cambiaría de forma notable el tiempo total
1123  del algoritmo.
1124  Otras posibilidades hubieran sido cargar todo el buffer en memoria y ordenarlo
1125  posteriormente (dependiendo del algoritmo de ordenamiento a utilizar puede
1126  ser más o menos rápido que el árbol y más o menos complicado de implementar)
1127  o hacer una búsqueda secuencial sobre un buffer desordenado (es más fácil
1128  de implementar pero claramente más lento).
1129  Una posible ventaja notable de leer el buffer primero y luego ordenarlo
1130  en memoria es que se necesita un sólo acceso al disco para llenar el buffer,
1131  mientras que al obtener uno a uno los valores puede generar muchos accesos
1132  a disco.
1133  Esto no debería ser muy notable ya que las funciones de acceso a archivos
1134  de la biblioteca estándar de C poseen un buffer interno, por lo que los
1135  accesos a disco probablemente sea muy poco aún cuando se obtienen uno a
1136  uno.
1137 \the_end