Statistics
| Revision:

root / trunk / libraries / libRaster / tmp / cache / Cache.java @ 10740

History | View | Annotate | Download (17.9 KB)

1

    
2
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
3
 *
4
 * Copyright (C) 2006 IVER T.I. and Generalitat Valenciana.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
19
 */
20
package org.gvsig.raster.dataaccess.cache;
21

    
22
/**
23
 * <P>
24
 * Esta clase representa a la cache raster. Consta de una ser?e de p?ginas (CachePages)
25
 * que son buffers con los bloques de datos cacheados en un instante dado. Esta cache tiene 
26
 * una estructura en forma de array donde cada elemento es una p?gina de cach?. Las p?ginas 
27
 * se agrupan en bloques de N p?ginas denominados grupos. La variable nelemsGroup contiene 
28
 * el n?mero de p?ginas de cada grupo.
29
 * </P>
30
 * <P>
31
 * La politica de reemplazo es que una p?gina siempre va a un conjunto determinado por el calculo
32
 * cto = pag % nelemsGroup. Si hay hueco vac?o en el grupo se a?adir? en el siguiente hueco pero
33
 * si hay que reeplazar se reeplazar? la p?gina que m?s tiempo haga su ?ltimo acceso. 
34
 * </P>
35
 * <P>
36
 * Esta cach? lleva el control de que p?ginas est?n cargadas a trav?s de un array de de booleanos
37
 * donde cada elemento representa a una p?gina de datos del raster. Si el elemento en la posici?n
38
 * N de dicho array es true significa que la p?gina est? cacheada. Si es false no lo estar?. 
39
 * </P>
40
 * <P>
41
 * La p?gina de datos actualmente accedida debe estar cacheada por lo que est? clase debe llevar
42
 * el control de que p?gina se est? accediendo o a sido accedida por ?ltima vez. La variable que
43
 * nos dice que p?gina est? siendo accedida es loadPage y pageBuffer ser? la variable que apunta
44
 * al buffer de esta p?gina. Cuando se cambia de p?gina en un acceso estas dos variables deben
45
 * cambiar a sus nuevos valores.
46
 * </P>
47
 * <P>
48
 * Otro par?metro que controla esta clase es que p?gina de cada grupo ha sido accedido con mayor 
49
 * frecuencia. Esto es ?til porque siempre se reemplaza la p?gina de un grupo que haga m?s tiempo
50
 * que haya sido accedida bajo la premisa de que "las p?ginas con accesos recientes tienen mayor 
51
 * probabilidad de volver a ser usadas". Esto es controlado por la variable lastAccess que es
52
 * usada para implementar el algoritmo LRU. Cada vez que una p?gina de un grupo es accedida su 
53
 * contador de lastAccess se pone a 0. El resto de contadores de las p?ginas del grupo se incrementa
54
 * en uno. Siempre se sustituye la p?gina del grupo con valor m?s grande en el contador.
55
 * </P>
56
 * 
57
 * @author Nacho Brodin (nachobrodin@gmail.com)
58
 *
59
 */
60
public class Cache{
61
        /**
62
         * Objeto que guarda y recupera trozos de cache de disco.
63
         */
64
        private ICacheDataSource dataSource = null;
65
        /**
66
         * Cada elemento es una p?gina del raster y dice si est? cacheada o no.
67
         */
68
        private boolean[] cacheada = null;
69
        /**
70
         * N?mero de p?gina cargada en accessPage.
71
         */
72
        private int numberInAccessPage = -1;
73
        /**
74
         * Buffer de datos de la p?gina actualmente accedida.
75
         */
76
        private PageBuffer accessPage = null;
77
        /**
78
         * P?ginas de cach?
79
         */
80
        private PageBuffer[] page = null;
81
        /**
82
         * Cada elemento del array es una p?gina de cach? y contiene el n?mero de p?gina cargada en 
83
         * esa posici?n.
84
         */
85
        private int[]        pageNumberInCache = null;
86
        /**
87
         * P?ginas de la cach?.
88
         */
89
        private CacheStruct cacheStruct = null;
90
        /**
91
         * ?ltimo acceso a las p?ginas de cada grupo.
92
         */
93
        private int[][] lastAccess = null;
94
        /**
95
         * Cada elemento representa una p?gina de cach? y dice si esta ha sido modificada desde que
96
         * fu? cargada en cach? o no.
97
         */
98
        private boolean[] modified = null;
99
        
100
        /**
101
         * Inicializamos la variables. Para ello creamos el objeto Cache que contendr? todos los 
102
         * par?metros necesarios para crear el array que controla los accesos m?s recientes y el
103
         * array que dice si una p?gina est? en memoria o no.
104
         * @param nBands N?mero de bandas
105
         * @param dataType Tipo de dato de la p?gina
106
         * @param dataSourceWidth ancho de la fuente de datos
107
         */
108
        public Cache(int nBands, int dataType, int dataSourceWidth, int dataSourceHeight){
109
                //Creamos la estructura de la cach?
110
                cacheStruct = new CacheStruct(nBands, dataType, dataSourceWidth, dataSourceHeight);
111
                
112
                //Inicializamos la antig?edad de acceso  
113
                lastAccess = new int[cacheStruct.getNGroups()][cacheStruct.getPagsPerGroup()];
114
                for(int i = 0; i < cacheStruct.getNGroups(); i ++)
115
                        for(int j = 0; j < cacheStruct.getPagsPerGroup(); j ++)
116
                                lastAccess[i][j] = -1;
117
                
118
                //Creamos el buffer de la cach?
119
                page = new PageBuffer[cacheStruct.getNPags()];
120
                pageNumberInCache = new int[cacheStruct.getNPags()];
121
                modified = new boolean[cacheStruct.getNPags()];
122
                
123
                cacheada = new boolean[cacheStruct.getNTotalPags()];
124
                for(int i = 0; i < cacheada.length; i++)
125
                        cacheada[i] = false;
126
                
127
                for(int i = 0; i < cacheStruct.getNPags(); i++){
128
                  page[i] = new PageBuffer(dataType, dataSourceWidth, cacheStruct.getHPag(), nBands, true);
129
                  pageNumberInCache[i] = -1;
130
                  modified[i] = false;
131
                }
132

    
133
        }
134
                
135
        /**
136
         * Obtiene el n?mero de bits por p?gina para poder calcular el desplazamiento binario
137
         * de la direcci?n de acceso de la petici?n. Es decir si se solicita un dato en la l?nea
138
         * 36 (en decimal) del raster 100100(en binario) y el desplazamiento es 4 bits el n?mero de 
139
         * p?gina resultante ser? 10(en binario) 2 (en decimal)
140
         * @return
141
         */
142
        public int getBitsPag() {
143
                return cacheStruct.getBitsPag();
144
        }
145

    
146
        /**
147
         * Obtiene la altura de la p?gina de cache en l?neas. 
148
         * @return N?mero de l?neas de altura de p?gina.
149
         */
150
        public int getHPag() {
151
                return cacheStruct.getHPag();
152
        }
153
        
154
        /**
155
         * Array de booleanos donde cada elemento es una p?gina del raster y dice si la p?gina 
156
         * est? cacheada o no.
157
         * @return true si la p?gina est? en cach? y false si no lo est?
158
         */
159
        public boolean isInCache(int nPag) {
160
                if(nPag < 0 || nPag >= cacheada.length)
161
                        return false;
162
                return cacheada[nPag];
163
        }
164
        
165
        /**
166
         * Marca una p?gina como cargada en cach?.
167
         * @param nPag N?mero de p?gina a marcar.
168
         */
169
        public void setPageAsLoadInCache(int nPag){
170
                if(nPag < 0 || nPag >= cacheada.length)
171
                        return;
172
                cacheada[nPag] = true;
173
        }
174
        
175
        /**
176
         * Desmarca una p?gina como cargada en cach?.
177
         * @param nPag N?mero de p?gina a desmarcar.
178
         */
179
        public void setPageAsNotLoadInCache(int nPag){
180
                if(nPag < 0 || nPag >= cacheada.length)
181
                        return;
182
                cacheada[nPag] = false;
183
        }
184
        
185
        /**
186
         * Obtiene el n?mero de p?gina del raster cargada en una p?gina de cach? especificada
187
         * en el par?metro. 
188
         * @param nCachePage N?mero de p?gina de cach? de la que se quiere saber que p?gina del 
189
         * raster hay cargada.
190
         * @return N?mero de p?gina del raster
191
         */
192
        public int getRasterPageNumberInPosition(int nCachePage){
193
                return pageNumberInCache[nCachePage];
194
        }
195
        
196
        /**
197
         * Obtiene el n?mero de p?gina del raster cargada en una p?gina de cach? especificada
198
         * en el par?metro. 
199
         * @param group Grupo en el que se encuentra la p?gina
200
         * @param posInGroup Posici?n dentro del grupo en el que est? la p?gina
201
         * @return N?mero de p?gina del raster
202
         */
203
        public int getRasterPageNumberInPosition(int group, int posInGroup){
204
                return pageNumberInCache[group * getPagsPerGroup() + posInGroup];
205
        }
206
        
207
        /**
208
         * Asigna el n?mero de p?gina del raster cargada en una p?gina de cach? especificada.
209
         * @param nCachePage N?mero de p?gina de cach? 
210
         * @param nRasterPage N?mero de p?gina de raster a asignar
211
         */
212
        public void setRasterPageNumberInPosition(int nCachePage, int nRasterPage){
213
                pageNumberInCache[nCachePage] = nRasterPage;
214
        }
215
        
216
        /**
217
         * Asigna el n?mero de p?gina del raster cargada en una p?gina de cach? especificada.
218
         * @param nCachePage N?mero de p?gina de cach? 
219
         * @param nRasterPage N?mero de p?gina de raster a asignar
220
         */
221
        public void setRasterPageNumberInPosition(int group, int posInGroup, int nRasterPage){
222
                pageNumberInCache[group * getPagsPerGroup() + posInGroup] = nRasterPage;
223
        }
224
        
225
        /**
226
         * Obtiene el n?mero de p?gina de cach? donde est? cargada la p?gina del raster
227
         * que se ha pasado por par?metro.
228
         * @param pag P?gina del raster
229
         * @return N?mero de p?gina del raster
230
         */
231
        public int getNumberCachePageFromNumberRasterPage(int pag){
232
                int group = pag % getNGroups();
233
                for(int i = 0; i < getPagsPerGroup(); i++)
234
                        if(pageNumberInCache[group + i] == pag)
235
                                return (group * getPagsPerGroup() + i);
236
                return -1;
237
        }
238
        
239
        /**
240
         * Obtiene el n?mero de p?gina de cach? (en formato grupo/p?gina dentro del grupo) 
241
         * donde est? cargada la p?gina del raster que se ha pasado por par?metro.
242
         * @param pag P?gina del raster
243
         * @return N?mero de p?gina del raster
244
         */
245
        public int[] getNumberGroupFromNumberRasterPage(int pag){
246
                int group = pag % getNGroups();
247
                for(int i = 0; i < getPagsPerGroup(); i++)
248
                        if(pageNumberInCache[(group * getPagsPerGroup()) + i] == pag)
249
                                return new int[]{group, i};
250
                return null;
251
        }
252
        
253
        /**
254
         * Obtiene el array que contiene los valores de la antig?edad del acceso dentro del
255
         * grupo. La primera dimensi?n del array corresponde al n?mero de grupo y la segunda
256
         * a los elementos del grupo. El elemento del grupo con un acceso m?s reciente tendr? 
257
         * un n?mero menor y el de mayor valor ser? el candidato para la sustituci?n en el pr?ximo
258
         * remplazamiento.
259
         * @return Array bidimensional con los valores de antig?edad.
260
         */
261
        public int[][] getLastAccess() {
262
                return lastAccess;
263
        }
264

    
265
        /**
266
         * Asigna un cero en la posici?n del array que contiene la antig?edad de acceso dentro 
267
         * del grupo. Esta operaci?n se realiza cada vez que se accede a un dato del la p?gina 
268
         * cacheada y significa que es la p?gina m?s recientemente accedida.
269
         * @param group N?mero de grupo
270
         * @param posInGroup Posici?n de la p?gina dentro del grupo.
271
         */
272
        public void setZeroInLastAccess(int group, int posInGroup){
273
                lastAccess[group][posInGroup] = 0;
274
        }
275
        
276
        /**
277
         * Obtiene el n?mero de p?gina cargada en el buffer
278
         * @return Entero con el n?mero de p?gina
279
         */
280
        public int getNumberInAccessPage() {
281
                return numberInAccessPage;
282
        }
283

    
284
        /**
285
         * Obtiene el n?mero de p?ginas que tiene cada grupo
286
         * @return Entero con el n?mero de p?ginas por grupo 
287
         */
288
        public int getPagsPerGroup() {
289
                return cacheStruct.getPagsPerGroup();
290
        }
291

    
292
        /**
293
         * Obtiene la p?gina de datos de la posici?n pag
294
         * @param pag N?mero de p?gina de cach? a recuperar
295
         * @return PageBuffer correspondiente a la p?gina recuperada
296
         */
297
        public PageBuffer getPageBufferFromNumberCachePage(int pag) {
298
                return page[pag];
299
        }
300
        
301
        /**
302
         * Obtiene la p?gina de datos a partir del n?mero de p?gina de raster
303
         * @param pag N?mero de p?gina raster a recuperar
304
         * @return PageBuffer correspondiente a la p?gina recuperada o null si no est? en cach?
305
         */
306
        public PageBuffer getPageBufferFromNumberRasterPage(int pag) {
307
                int group = pag % getNGroups();
308
                for(int i = 0; i < getPagsPerGroup(); i++)
309
                        if(pageNumberInCache[group * getPagsPerGroup() + i] == pag)
310
                                return page[group * getPagsPerGroup() + i];
311
                return null;
312
        }
313
        
314
        /**
315
         * Obtiene la p?gina de datos del grupo definido en el par?metro group y de la 
316
         * posici?n pag dentro de ese grupo.
317
         * @param group Grupo de la p?gina requerida
318
         * @param pag N?mero de p?gina dentro del grupo
319
         * @return PageBuffer correspondiente a la p?gina recuperada
320
         */
321
        public PageBuffer getPageBuffer(int group, int posInGroup) {
322
                return page[group * getPagsPerGroup() + posInGroup];
323
        }
324
        
325
        /**
326
         * Obtiene la p?gina de datos actualmente accedida
327
         * @return PageBuffer correspondiente a la p?gina que se est? accediendo
328
         */
329
        public PageBuffer getAccessPage() {
330
                return accessPage;
331
        }
332
        
333
        /**
334
         * Asigna el buffer de la p?gina accedida por referencia
335
         * @param pb
336
         */
337
        public void setAccessPage(PageBuffer pb, int pagNumber){
338
                accessPage = pb;
339
                numberInAccessPage = pagNumber;
340
        }
341
        
342
        /**
343
         * Consulta si una p?gina de cach? ha sido modificada desde que se carg? en cach? o no.
344
         * @param nCachePag N?mero de p?gina de cach? (posici?n de esta)
345
         * @return true si ha sido modificada y false si no lo ha sido.
346
         */
347
        public boolean isModified(int nCachePag){
348
                return modified[nCachePag];
349
        }
350

    
351
        /**
352
         * Consulta si una p?gina de cach? ha sido modificada desde que se carg? en cach? o no.
353
         * @param group Grupo en el que se encuentra la p?gina
354
         * @param posInGroup Posici?n dentro del grupo en el que est? la p?gina
355
         * @return true si ha sido modificada y false si no lo ha sido.
356
         */
357
        public boolean isModified(int group, int posInGroup){
358
                return modified[group * getPagsPerGroup() + posInGroup];
359
        }
360

    
361
        /**
362
         * Pone como modificada una p?gina de cach?
363
         * @param nCachePag N?mero de p?gina de cach? (posici?n de esta)
364
         */
365
        public void setModify(int nCachePag){
366
                modified[nCachePag] = true;        
367
        }
368
        
369
        /**
370
         * Pone como modificada una p?gina de cach?
371
         * @param group Grupo en el que se encuentra la p?gina
372
         * @param posInGroup Posici?n dentro del grupo en el que est? la p?gina
373
         */
374
        public void setModify(int group, int posInGroup){
375
                modified[group * getPagsPerGroup() + posInGroup] = true;        
376
        }
377
        
378
        /**
379
         * Pone como no modificada una p?gina de cach?
380
         * @param nCachePag N?mero de p?gina de cach? (posici?n de esta)
381
         */
382
        public void unsetModify(int nCachePag){
383
                modified[nCachePag] = false;        
384
        }
385
        
386
        /**
387
         * Pone como no modificada una p?gina de cach?
388
         * @param group Grupo en el que se encuentra la p?gina
389
         * @param posInGroup Posici?n dentro del grupo en el que est? la p?gina
390
         */
391
        public void unsetModify(int group, int posInGroup){
392
                modified[group * getPagsPerGroup() + posInGroup] = false;        
393
        }
394
        
395
        /**
396
         * Obtiene el n?mero de p?ginas de la cach?
397
         * @return N?mero total de p?ginas de la cach?
398
         */
399
        public int getNPags() {
400
                return cacheStruct.getNPags();
401
        }
402
        
403
        /**
404
         * Obtiene el n?mero de bandas
405
         * @return N?mero de bandas
406
         */
407
        public int getNBands() {
408
                return cacheStruct.getNBands();
409
        }
410
        
411
        /**
412
         * Obtiene la estructura de ca cach?
413
         * @return CacheStruct
414
         */
415
        public CacheStruct getCacheStruct() {
416
                return cacheStruct;
417
        }
418
        
419
        /**
420
         * Obtiene el n?mero de grupos de cach?
421
         * @return N?mero de grupos
422
         */
423
        public int getNGroups() {
424
                return cacheStruct.getNGroups();
425
        }
426
        
427
        /**
428
         * Obtiene el n?mero total de p?ginas del raster
429
         * @return N?mero total de p?ginas
430
         */
431
        public int getNTotalPags() {
432
                return cacheStruct.getNTotalPags();
433
        }
434
        
435
        /**
436
         * Obtiene el array con los n?meros de p?gina que hay cargados
437
         * en cada bloque de cache
438
         * @return array con los n?mero de p?gina
439
         */
440
        public int[] getPageNumberInCache(){
441
                return this.pageNumberInCache;
442
        }
443
        
444
        /**
445
         * Para extraer el desplazamiento de una direcci?n (l?nea de raster) hay que hacer una operaci?n And con 
446
         * con la altura de la p?gina -1. Por ejemplo, una p?gina de 16 l?neas de altura el desplazamiento ser?
447
         * 16 - 1 = 15 porque 15 en binario es 1111.
448
         * 
449
         * Si queremos acceder a la linea del raster n?mero 83 (1010011) realizando la operaci?n And con el valor del
450
         * desplazamiento obtenemos (0001111 & 1010011 = 0000011), es decir el valor 3 en decimal. Esto quiere decir
451
         * que la l?nea 83 del raster es la 3 de su p?gina. 
452
         * @return valor del desplazamiento
453
         */
454
        public int getOffset() {
455
                return cacheStruct.getOffset();
456
        }
457
        
458
        /**
459
         * Convierte una p?gina dentro de un grupo de la cach? en un n?mero de 
460
         * p?gina de cach?. Por ejemplo, en una cach? de 10 grupos y 5 p?ginas por grupo
461
         * la p?gina 2 del grupo 4 devolver? el 23 (5 * 4 + 3 = 23) teniendo en cuenta que
462
         * la p?gina y el grupo cero tambi?n cuentan.  
463
         * @param group
464
         * @param pageInGroup
465
         * @return
466
         */
467
        public int convertPageInGroupToPageInCache(int group, int pageInGroup){
468
                return (group * cacheStruct.getPagsPerGroup() + pageInGroup);
469
        }
470

    
471
        /**
472
         * Actualiza los ?ltimos accesos del grupo pasado por par?metro. Se incrementar? 
473
         * uno en todas las p?ginas del conjunto a excepci?n de las que valen -1 ya que 
474
         * esto significa que no hay p?gina cargada en dicha posici?n.
475
         * @param group N?mero de grupo a actualizar sus accesos
476
         * @return La posici?n del elemento del grupo con valor m?ximo. Este elemento 
477
         * es el candidato para el reemplazo.
478
         */
479
        public int updateLastAccess(int group){
480
                int max = Integer.MIN_VALUE;
481
                int posMax = 0;
482
                for(int i = 0; i < getPagsPerGroup(); i++){
483
                        if(getLastAccess()[group][i] >= 0)
484
                                getLastAccess()[group][i] ++;
485
                        
486
                        if(getLastAccess()[group][i] > max){
487
                                max = getLastAccess()[group][i];
488
                                posMax = i;
489
                        }
490
                }
491
                return posMax;
492
        }
493
        
494
        /**
495
         * Obtiene la posici?n del grupo de la p?gina a reemplazar, es decir la de m?ximo valor
496
         * en el vector lastAccess.
497
         * @param group N?mero de grupo a obtener la p?gina de reemplazo
498
         * @return La posici?n del elemento del grupo con valor m?ximo. Este elemento 
499
         * es el candidato para el reemplazo.
500
         */
501
        public int posInGroupPagToReplace(int group){
502
                int max = Integer.MIN_VALUE;
503
                int posMax = 0;
504
                for(int i = 0; i < getPagsPerGroup(); i++){
505
                        if(getLastAccess()[group][i] > max){
506
                                max = getLastAccess()[group][i];
507
                                posMax = i;
508
                        }
509
                }
510
                return posMax;
511
        } 
512
        
513
        /**
514
         * Asigna el objeto que guarda y recupera trozos de cache de disco.
515
         * @param dataSource
516
         */
517
        public void setDataSource(ICacheDataSource dataSource){
518
                this.dataSource = dataSource;
519
        }
520
        
521
        /**
522
         * Recupera el objeto que guarda y recupera trozos de cache de disco.
523
         * @return dataSource
524
         */
525
        public ICacheDataSource getDataSource(){
526
                return dataSource;
527
        }
528
        
529
        /**
530
         * Imprime la informaci?n de estructura de cach?
531
         */
532
        public void show(){
533
                cacheStruct.show();
534
                System.out.println("Cacheada:");
535
                for(int i = 0; i < cacheada.length; i++)
536
                        System.out.print(i + "=" + cacheada[i]+" ");
537
                System.out.println();
538
                System.out.println("LastAccess:");
539
                for(int i = 0; i < cacheStruct.getNGroups(); i++){
540
                        System.out.println("Grupo " + i +":");
541
                        for(int j = 0; j < cacheStruct.getPagsPerGroup(); j++)
542
                                System.out.println("elem " + j + " : " + "Page " + pageNumberInCache[i * cacheStruct.getPagsPerGroup() + j] + " : " + lastAccess[i][j]);
543
                
544
                }
545
        }
546
        
547
}