Subversion Repositories Applications.framework

Rev

Rev 269 | Rev 288 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
269 jpm 1
<?php
2
class CacheSqlite {
3
	/**
282 jpm 4
	 * Options disponibles :
269 jpm 5
	 *
282 jpm 6
	 * ====> (string) stockage_chemin :
7
	 * Chemin vers le fichier contenant la base SQLite.
8
	 *
269 jpm 9
	 *
282 jpm 10
	 * ====> (int) defragmentation_auto :
11
	 * - Désactive / Régler le processus de défragmentation automatique
12
	 * - Le processus de défragmentation automatiques réduit la taille du fichier contenant la base de données
13
	 *   quand un ajout ou une suppression de cache est réalisée :
14
	 *	 0			   => pas de défragmentation automatique
15
	 *	 1			   => défragmentation automatique systématique
16
	 *	 x (integer) > 1 => défragmentation automatique toutes les 1 fois (au hasard) sur x ajout ou suppression de cache
269 jpm 17
	 *
282 jpm 18
	 * @var array options disponibles
269 jpm 19
	 */
20
	protected $options = array(
21
		'stockage_chemin' => null,
22
		'defragmentation_auto' => 10
23
	);
24
 
25
	/**
26
	 * DB ressource
27
	 *
28
	 * @var mixed $db
29
	 */
30
	private $bdd = null;
31
 
32
	/**
33
	 * Boolean to store if the structure has benn checked or not
34
	 *
35
	 * @var boolean $structure_ok
36
	 */
37
	private $structure_ok = false;
38
 
39
	private $Cache = null;
40
 
41
	/**
42
	 * Constructor
43
	 *
44
	 * @param  array $options Associative array of options
45
	 * @throws Zend_cache_Exception
46
	 * @return void
47
	 */
48
	public function __construct(array $options = array(), Cache $cache) {
49
		$this->Cache = $cache;
50
		if (extension_loaded('sqlite')) {
282 jpm 51
			$this->initialiserOptionsParConfig();
269 jpm 52
			$this->setOptions($options);
53
		} else {
54
			$e = "Impossible d'utiliser le cache SQLITE car l'extenssion 'sqlite' n'est pas chargée dans l'environnement PHP courrant.";
55
			trigger_error($e, E_USER_ERROR);
56
		}
57
	}
58
 
282 jpm 59
	private function initialiserOptionsParConfig() {
60
		while (list($nom, $valeur) = each($this->options)) {
61
			if (Config::existe($nom)) {
62
				$this->options[$nom] = Config::get($nom);
63
			}
64
		}
65
	}
66
 
269 jpm 67
	/**
68
	 * Destructor
69
	 *
70
	 * @return void
71
	 */
72
	public function __destruct() {
73
		@sqlite_close($this->getConnexion());
74
	}
75
 
76
	private function setOptions($options) {
77
		while (list($nom, $valeur) = each($options)) {
78
			if (!is_string($nom)) {
79
				trigger_error("Nom d'option incorecte : $nom", E_USER_WARNING);
80
			}
81
			$nom = strtolower($nom);
82
			if (array_key_exists($nom, $this->options)) {
83
				$this->options[$nom] = $valeur;
84
			}
85
		}
86
	}
87
 
88
	public function setEmplacement($emplacement) {
89
	 	if (extension_loaded('sqlite')) {
90
			$this->options['stockage_chemin'] = $emplacement;
91
		} else {
92
			trigger_error("Impossible d'utiliser le mode de sotckage SQLite car l'extenssion 'sqlite' n'est pas chargé dans ".
93
				"l'environnement PHP courrant.", E_USER_ERROR);
94
		}
95
	}
96
 
97
	/**
98
	 * Test if a cache is available for the given id and (if yes) return it (false else)
99
	 *
100
	 * @param  string  $id					 Cache id
101
	 * @param  boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
102
	 * @return string|false Cached datas
103
	 */
104
	public function charger($id, $ne_pas_tester_validiter_du_cache = false) {
105
		$this->verifierEtCreerStructureBdd();
106
		$requete = "SELECT content FROM cache WHERE id = '$id'".
107
			(($ne_pas_tester_validiter_du_cache) ? '' : ' AND (expire = 0 OR expire > '.time().')');
108
		$resultat = $this->requeter($requete);
109
		$ligne = @sqlite_fetch_array($resultat);
110
		return ($ligne) ? $ligne['content'] : false;
111
	}
112
 
113
	/**
114
	 * Test if a cache is available or not (for the given id)
115
	 *
116
	 * @param string $id Cache id
117
	 * @return mixed|false (a cache is not available) or "last modified" timestamp (int) of the available cache record
118
	 */
119
	public function tester($id) {
120
		$this->verifierEtCreerStructureBdd();
121
		$requete = "SELECT lastModified FROM cache WHERE id = '$id' AND (expire = 0 OR expire > ".time().')';
122
		$resultat = $this->requeter($requete);
123
		$ligne = @sqlite_fetch_array($resultat);
124
		return ($ligne) ? ((int) $ligne['lastModified']) : false;
125
	}
126
 
127
	/**
128
	 * Save some string datas into a cache record
129
	 *
130
	 * Note : $data is always "string" (serialization is done by the
131
	 * core not by the backend)
132
	 *
133
	 * @param  string $data			 Datas to cache
134
	 * @param  string $id			   Cache id
135
	 * @param  array  $tags			 Array of strings, the cache record will be tagged by each string entry
136
	 * @param  int	$specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
137
	 * @throws Zend_Cache_Exception
138
	 * @return boolean True if no problem
139
	 */
140
	public function sauver($donnees, $id, $tags = array(), $duree_vie_specifique = false) {
141
		$this->verifierEtCreerStructureBdd();
142
		$donnees = @sqlite_escape_string($donnees);
143
		$timestamp_courrant = time();
144
		$expiration = $this->Cache->getTimestampExpiration($duree_vie_specifique);
145
 
146
		$this->requeter("DELETE FROM cache WHERE id = '$id'");
147
		$sql = "INSERT INTO cache (id, content, lastModified, expire) VALUES ('$id', '$donnees', $timestamp_courrant, $expiration)";
148
		$resultat = $this->requeter($sql);
149
		if (!$resultat) {
150
			// TODO : ajouter un log sauver() : impossible de stocker le cache d'id '$id'
151
			Debug::printr("sauver() : impossible de stocker le cache d'id '$id'");
152
			$resultat =  false;
153
		} else {
154
			$resultat = true;
155
			foreach ($tags as $tag) {
156
				$resultat = $this->enregisterTag($id, $tag) && $resultat;
157
			}
158
		}
159
		return $resultat;
160
	}
161
 
162
	/**
163
	 * Remove a cache record
164
	 *
165
	 * @param  string $id Cache id
166
	 * @return boolean True if no problem
167
	 */
168
	public function supprimer($id) {
169
		$this->verifierEtCreerStructureBdd();
170
		$resultat = $this->requeter("SELECT COUNT(*) AS nbr FROM cache WHERE id = '$id'");
171
		$resultat_nbre = @sqlite_fetch_single($resultat);
172
		$suppression_cache = $this->requeter("DELETE FROM cache WHERE id = '$id'");
173
		$suppression_tags = $this->requeter("DELETE FROM tag WHERE id = '$id'");
174
		$this->defragmenterAutomatiquement();
175
		return ($resultat_nbre && $suppression_cache && $suppression_tags);
176
	}
177
 
178
	/**
179
	 * Clean some cache records
180
	 *
181
	 * Available modes are :
182
	 * Zend_Cache::CLEANING_MODE_ALL (default)	=> remove all cache entries ($tags is not used)
183
	 * Zend_Cache::CLEANING_MODE_OLD			  => remove too old cache entries ($tags is not used)
184
	 * Zend_Cache::CLEANING_MODE_MATCHING_TAG	 => remove cache entries matching all given tags
185
	 *											   ($tags can be an array of strings or a single string)
186
	 * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
187
	 *											   ($tags can be an array of strings or a single string)
188
	 * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
189
	 *											   ($tags can be an array of strings or a single string)
190
	 *
191
	 * @param  string $mode Clean mode
192
	 * @param  array  $tags Array of tags
193
	 * @return boolean True if no problem
194
	 */
195
	public function nettoyer($mode = Cache::NETTOYAGE_MODE_TOUS, $tags = array()) {
196
		$this->verifierEtCreerStructureBdd();
197
		$retour = $this->nettoyerSqlite($mode, $tags);
198
		$this->defragmenterAutomatiquement();
199
		return $retour;
200
	}
201
 
202
	/**
203
	 * Return an array of stored cache ids
204
	 *
205
	 * @return array array of stored cache ids (string)
206
	 */
207
	public function getIds() {
208
		$this->verifierEtCreerStructureBdd();
209
		$resultat = $this->requeter('SELECT id FROM cache WHERE (expire = 0 OR expire > '.time().')');
210
		$retour = array();
211
		while ($id = @sqlite_fetch_single($resultat)) {
212
			$retour[] = $id;
213
		}
214
		return $retour;
215
	}
216
 
217
	/**
218
	 * Return an array of stored tags
219
	 *
220
	 * @return array array of stored tags (string)
221
	 */
222
	public function getTags() {
223
		$this->verifierEtCreerStructureBdd();
224
		$resultat = $this->requeter('SELECT DISTINCT(name) AS name FROM tag');
225
		$retour = array();
226
		while ($id = @sqlite_fetch_single($resultat)) {
227
			$retour[] = $id;
228
		}
229
		return $retour;
230
	}
231
 
232
	/**
233
	 * Return an array of stored cache ids which match given tags
234
	 *
235
	 * In case of multiple tags, a logical AND is made between tags
236
	 *
237
	 * @param array $tags array of tags
238
	 * @return array array of matching cache ids (string)
239
	 */
240
	public function getIdsAvecLesTags($tags = array()) {
241
		$this->verifierEtCreerStructureBdd();
242
		$premier = true;
243
		$ids = array();
244
		foreach ($tags as $tag) {
245
			$resultat = $this->requeter("SELECT DISTINCT(id) AS id FROM tag WHERE name='$tag'");
246
			if ($resultat) {
247
				$lignes = @sqlite_fetch_all($resultat, SQLITE_ASSOC);
248
				$ids_tmp = array();
249
				foreach ($lignes as $ligne) {
250
					$ids_tmp[] = $ligne['id'];
251
				}
252
				if ($premier) {
253
					$ids = $ids_tmp;
254
					$premier = false;
255
				} else {
256
					$ids = array_intersect($ids, $ids_tmp);
257
				}
258
			}
259
		}
260
 
261
		$retour = array();
262
		if (count($ids) > 0) {
263
			foreach ($ids as $id) {
264
				$retour[] = $id;
265
			}
266
		}
267
		return $retour;
268
	}
269
 
270
	/**
271
	 * Return an array of stored cache ids which don't match given tags
272
	 *
273
	 * In case of multiple tags, a logical OR is made between tags
274
	 *
275
	 * @param array $tags array of tags
276
	 * @return array array of not matching cache ids (string)
277
	 */
278
	public function getIdsSansLesTags($tags = array()) {
279
		$this->verifierEtCreerStructureBdd();
280
		$resultat = $this->requeter('SELECT id FROM cache');
281
		$lignes = @sqlite_fetch_all($resultat, SQLITE_ASSOC);
282
		$retour = array();
283
		foreach ($lignes as $ligne) {
284
			$id = $ligne['id'];
285
			$correspondance = false;
286
			foreach ($tags as $tag) {
287
				$resultat = $this->requeter("SELECT COUNT(*) AS nbr FROM tag WHERE name = '$tag' AND id = '$id'");
288
				if ($resultat) {
289
					$nbre = (int) @sqlite_fetch_single($resultat);
290
					if ($nbre > 0) {
291
						$correspondance = true;
292
					}
293
				}
294
			}
295
			if (!$correspondance) {
296
				$retour[] = $id;
297
			}
298
		}
299
		return $retour;
300
	}
301
 
302
	/**
303
	 * Return an array of stored cache ids which match any given tags
304
	 *
305
	 * In case of multiple tags, a logical AND is made between tags
306
	 *
307
	 * @param array $tags array of tags
308
	 * @return array array of any matching cache ids (string)
309
	 */
310
	public function getIdsAvecUnTag($tags = array()) {
311
		$this->verifierEtCreerStructureBdd();
312
		$premier = true;
313
		$ids = array();
314
		foreach ($tags as $tag) {
315
			$resultat = $this->requeter("SELECT DISTINCT(id) AS id FROM tag WHERE name = '$tag'");
316
			if ($resultat) {
317
				$lignes = @sqlite_fetch_all($resultat, SQLITE_ASSOC);
318
				$ids_tmp = array();
319
				foreach ($lignes as $ligne) {
320
					$ids_tmp[] = $ligne['id'];
321
				}
322
				if ($premier) {
323
					$ids = $ids_tmp;
324
					$premier = false;
325
				} else {
326
					$ids = array_merge($ids, $ids_tmp);
327
				}
328
			}
329
		}
330
 
331
		$retour = array();
332
		if (count($ids) > 0) {
333
			foreach ($ids as $id) {
334
				$retour[] = $id;
335
			}
336
		}
337
		return $retour;
338
	}
339
 
340
	/**
341
	 * Return the filling percentage of the backend storage
342
	 *
343
	 * @throws Zend_Cache_Exception
344
	 * @return int integer between 0 and 100
345
	 */
346
	public function getPourcentageRemplissage() {
347
		$dossier = dirname($this->options['stockage_chemin']);
348
		$libre = disk_free_space($dossier);
349
		$total = disk_total_space($dossier);
350
 
351
		$pourcentage = 0;
352
		if ($total == 0) {
353
			trigger_error("Impossible d'utiliser la fonction disk_total_space", E_USER_WARNING);
354
		} else {
355
			$pourcentage = ($libre >= $total) ? 100 : ((int) (100. * ($total - $libre) / $total));
356
		}
357
		return $pourcentage;
358
	}
359
 
360
	/**
361
	 * Return an array of metadatas for the given cache id
362
	 *
363
	 * The array must include these keys :
364
	 * - expire : the expire timestamp
365
	 * - tags : a string array of tags
366
	 * - mtime : timestamp of last modification time
367
	 *
368
	 * @param string $id cache id
369
	 * @return array array of metadatas (false if the cache id is not found)
370
	 */
371
	public function getMetadonnees($id) {
372
		$this->verifierEtCreerStructureBdd();
373
		$tags = array();
374
		$resultat = $this->requeter("SELECT name FROM tag WHERE id = '$id'");
375
		if ($resultat) {
376
			$lignes = @sqlite_fetch_all($resultat, SQLITE_ASSOC);
377
			foreach ($lignes as $ligne) {
378
				$tags[] = $ligne['name'];
379
			}
380
		}
381
		$resultat = $this->requeter("SELECT lastModified, expire FROM cache WHERE id = '$id'");
382
		if ($resultat) {
383
			$ligne = @sqlite_fetch_array($resultat, SQLITE_ASSOC);
384
			$resultat = array(
385
				'tags' => $tags,
386
				'mtime' => $ligne['lastModified'],
387
				'expiration' => $ligne['expire']);
388
		} else {
389
			$resultat = false;
390
		}
391
		return $resultat;
392
	}
393
 
394
	/**
395
	 * Give (if possible) an extra lifetime to the given cache id
396
	 *
397
	 * @param string $id cache id
398
	 * @param int $extraLifetime
399
	 * @return boolean true if ok
400
	 */
401
	public function ajouterSupplementDureeDeVie($id, $supplement_duree_de_vie) {
402
		$this->verifierEtCreerStructureBdd();
403
		$augmentation = false;
404
		$requete = "SELECT expire FROM cache WHERE id = '$id' AND (expire = 0 OR expire > ".time().')';
405
		$resultat = $this->requeter($requete);
406
		if ($resultat) {
407
			$expiration = @sqlite_fetch_single($resultat);
408
			$nouvelle_expiration = $expiration + $supplement_duree_de_vie;
409
			$resultat = $this->requeter('UPDATE cache SET lastModified = '.time().", expire = $nouvelle_expiration WHERE id = '$id'");
410
			$augmentation = ($resultat) ? true : false;
411
		}
412
		return $augmentation;
413
	}
414
 
415
	/**
416
	 * Return the connection resource
417
	 *
418
	 * If we are not connected, the connection is made
419
	 *
420
	 * @throws Zend_Cache_Exception
421
	 * @return resource Connection resource
422
	 */
423
	private function getConnexion() {
424
		if (!is_resource($this->bdd)) {
425
			if ($this->options['stockage_chemin'] === null) {
426
				$e = "L'emplacement du chemin vers le fichier de la base de données SQLite n'a pas été défini";
427
				trigger_error($e, E_USER_ERROR);
428
			} else {
429
				$this->bdd = sqlite_open($this->options['stockage_chemin']);
430
				if (!(is_resource($this->bdd))) {
431
					$e = "Impossible d'ouvrir le fichier '".$this->options['stockage_chemin']."' de la base de données SQLite.";
432
					trigger_error($e, E_USER_ERROR);
433
					$this->bdd = null;
434
				}
435
			}
436
		}
437
		return $this->bdd;
438
	}
439
 
440
	/**
441
	 * Execute une requête SQL sans afficher de messages d'erreur.
442
	 *
443
	 * @param string $requete requête SQL
444
	 * @return mixed|false resultats de la requête
445
	 */
446
	private function requeter($requete) {
447
		$bdd = $this->getConnexion();
448
		//Debug::printr($requete);
449
		$resultat = (is_resource($bdd)) ? @sqlite_query($bdd, $requete, SQLITE_ASSOC, $e_sqlite) : false;
450
		if (is_resource($bdd) && ! $resultat) {
451
			Debug::printr("Erreur SQLITE :\n$e_sqlite\nPour la requête :\n$requete\nRessource : $bdd");
452
		}
453
		return $resultat;
454
	}
455
 
456
	/**
457
	 * Deal with the automatic vacuum process
458
	 *
459
	 * @return void
460
	 */
461
	private function defragmenterAutomatiquement() {
462
		if ($this->options['defragmentation_auto'] > 0) {
463
			$rand = rand(1, $this->options['defragmentation_auto']);
464
			if ($rand == 1) {
465
				$this->requeter('VACUUM');
466
				@sqlite_close($this->getConnexion());
467
			}
468
		}
469
	}
470
 
471
	/**
472
	 * Register a cache id with the given tag
473
	 *
474
	 * @param  string $id  Cache id
475
	 * @param  string $tag Tag
476
	 * @return boolean True if no problem
477
	 */
478
	private function enregisterTag($id, $tag) {
479
		$requete_suppression = "DELETE FROM tag WHERE name = '$tag' AND id = '$id'";
480
		$resultat = $this->requeter($requete_suppression);
481
		$requete_insertion = "INSERT INTO tag(name,id) VALUES ('$tag','$id')";
482
		$resultat = $this->requeter($requete_insertion);
483
		if (!$resultat) {
484
			// TODO : ajouter un log -> impossible d'enregistrer le tag=$tag pour le cache id=$id");
485
			Debug::printr("Impossible d'enregistrer le tag=$tag pour le cache id=$id");
486
		}
487
		return ($resultat) ? true : false;
488
	}
489
 
490
	/**
491
	 * Build the database structure
492
	 *
493
	 * @return false
494
	 */
495
	private function creerStructure() {
496
		Debug::printr("création de la str");
497
		$this->requeter('DROP INDEX IF EXISTS tag_id_index');
498
		$this->requeter('DROP INDEX IF EXISTS tag_name_index');
499
		$this->requeter('DROP INDEX IF EXISTS cache_id_expire_index');
500
		$this->requeter('DROP TABLE IF EXISTS version');
501
		$this->requeter('DROP TABLE IF EXISTS cache');
502
		$this->requeter('DROP TABLE IF EXISTS tag');
503
		$this->requeter('CREATE TABLE version (num INTEGER PRIMARY KEY)');
504
		$this->requeter('CREATE TABLE cache(id TEXT PRIMARY KEY, content BLOB, lastModified INTEGER, expire INTEGER)');
505
		$this->requeter('CREATE TABLE tag (name TEXT, id TEXT)');
506
		$this->requeter('CREATE INDEX tag_id_index ON tag(id)');
507
		$this->requeter('CREATE INDEX tag_name_index ON tag(name)');
508
		$this->requeter('CREATE INDEX cache_id_expire_index ON cache(id, expire)');
509
		$this->requeter('INSERT INTO version (num) VALUES (1)');
510
	}
511
 
512
	/**
513
	 * Check if the database structure is ok (with the good version)
514
	 *
515
	 * @return boolean True if ok
516
	 */
517
	private function verifierBddStructureVersion() {
518
		$version_ok = false;
519
		$resultat = $this->requeter('SELECT num FROM version');
520
		if ($resultat) {
521
			$ligne = @sqlite_fetch_array($resultat);
522
			if ($ligne) {
523
				if (((int) $ligne['num']) == 1) {
524
					$version_ok = true;
525
				} else {
526
					// TODO : ajouter un log CacheSqlite::verifierBddStructureVersion() : vielle version de la structure de la base de données de cache détectée => le cache est entrain d'être supprimé
527
				}
528
			}
529
		}
530
		return $version_ok;
531
	}
532
 
533
	/**
534
	 * Clean some cache records
535
	 *
536
	 * Available modes are :
537
	 * Zend_Cache::CLEANING_MODE_ALL (default)	=> remove all cache entries ($tags is not used)
538
	 * Zend_Cache::CLEANING_MODE_OLD			  => remove too old cache entries ($tags is not used)
539
	 * Zend_Cache::CLEANING_MODE_MATCHING_TAG	 => remove cache entries matching all given tags
540
	 *											   ($tags can be an array of strings or a single string)
541
	 * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
542
	 *											   ($tags can be an array of strings or a single string)
543
	 * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
544
	 *											   ($tags can be an array of strings or a single string)
545
	 *
546
	 * @param  string $mode Clean mode
547
	 * @param  array  $tags Array of tags
548
	 * @return boolean True if no problem
549
	 */
550
	private function nettoyerSqlite($mode = Cache::NETTOYAGE_MODE_TOUS, $tags = array()) {
551
		$nettoyage_ok = false;
552
		switch ($mode) {
553
			case Cache::NETTOYAGE_MODE_TOUS:
554
				$suppression_cache = $this->requeter('DELETE FROM cache');
555
				$suppression_tag = $this->requeter('DELETE FROM tag');
556
				$nettoyage_ok = $suppression_cache && $suppression_tag;
557
				break;
558
			case Cache::NETTOYAGE_MODE_EXPIRATION:
559
				$mktime = time();
560
				$suppression_tag = $this->requeter("DELETE FROM tag WHERE id IN (SELECT id FROM cache WHERE expire > 0 AND expire <= $mktime)");
561
				$suppression_cache = $this->requeter("DELETE FROM cache WHERE expire > 0 AND expire <= $mktime");
562
				return $suppression_tag && $suppression_cache;
563
				break;
564
			case Cache::NETTOYAGE_MODE_AVEC_LES_TAGS:
565
				$ids = $this->getIdsAvecLesTags($tags);
566
				$resultat = true;
567
				foreach ($ids as $id) {
568
					$resultat = $this->supprimer($id) && $resultat;
569
				}
570
				return $resultat;
571
				break;
572
			case Cache::NETTOYAGE_MODE_SANS_LES_TAGS:
573
				$ids = $this->getIdsSansLesTags($tags);
574
				$resultat = true;
575
				foreach ($ids as $id) {
576
					$resultat = $this->supprimer($id) && $resultat;
577
				}
578
				return $resultat;
579
				break;
580
			case Cache::NETTOYAGE_MODE_AVEC_UN_TAG:
581
				$ids = $this->getIdsAvecUnTag($tags);
582
				$resultat = true;
583
				foreach ($ids as $id) {
584
					$resultat = $this->supprimer($id) && $resultat;
585
				}
586
				return $resultat;
587
				break;
588
			default:
589
				break;
590
		}
591
		return $nettoyage_ok;
592
	}
593
 
594
	/**
595
	 * Check if the database structure is ok (with the good version), if no : build it
596
	 *
597
	 * @throws Zend_Cache_Exception
598
	 * @return boolean True if ok
599
	 */
600
	private function verifierEtCreerStructureBdd() {
601
		if (! $this->structure_ok) {
602
			if (! $this->verifierBddStructureVersion()) {
603
				$this->creerStructure();
604
				if (! $this->verifierBddStructureVersion()) {
605
					$e = "Impossible de construire la base de données de cache dans ".$this->options['stockage_chemin'];
606
					trigger_error($e, E_USER_WARNING);
607
					$this->structure_ok = false;
608
				}
609
			}
610
			$this->structure_ok = true;
611
		}
612
		return $this->structure_ok;
613
	}
614
 
615
}
616
?>