;;; gh-cache.el --- caching for gh.el ;; Copyright (C) 2011 Yann Hodique ;; Author: Yann Hodique ;; Keywords: ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This file is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; ;;; Code: (eval-when-compile (require 'cl)) ;;;###autoload (require 'eieio) (require 'pcache) (defconst gh-cache-outdated-expiration-delay (* 60 60 24)) (defconst gh-cache-internal-version-constant 3) (defconst gh-cache-version-constant (format "%s/gh-%s" pcache-version-constant gh-cache-internal-version-constant)) (defclass gh-cache (pcache-repository) ((version-constant :allocation :class) (entries :initarg :entries :initform (make-hash-table :test 'equal)) (safe-methods :allocation :class :initform ("HEAD" "GET" "OPTIONS" "TRACE")) (invalidation-chain :allocation :class :initform nil) (entry-cls :initarg :entry-cls :initform gh-cache-entry))) (oset-default 'gh-cache version-constant gh-cache-version-constant) (defclass gh-cache-entry (pcache-entry) ((etag :initarg :etag :initform nil) (outdated :initarg :outdated :initform nil) ;; (ttl :initarg :ttl :initform 0) )) (defmethod pcache-invalidate :after ((cache gh-cache) key) (let ((resource (car key))) (pcache-map cache #'(lambda (k v) (when (equal (car k) resource) (pcache-invalidate cache k)))) (dolist (next (oref cache invalidation-chain)) (let ((nextresource (replace-regexp-in-string (car next) (cdr next) resource))) (when (not (equal nextresource resource)) (pcache-map cache #'(lambda (k v) (when (equal (car k) nextresource) (pcache-invalidate cache k))))))))) (defmethod pcache-get ((cache gh-cache) key &optional default) (let* ((table (oref cache :entries)) (entry (gethash key table))) (if (not entry) default (unless (pcache-entry-valid-p entry) (oset entry :outdated t)) (oref entry :value)))) (defmethod pcache-has ((cache pcache-repository) key) (let* ((default (make-symbol ":nil")) (table (oref cache :entries)) (entry (gethash key table default))) (not (eq entry default)))) (defmethod pcache-purge-invalid ((cache gh-cache)) (let ((table (oref cache :entries))) (maphash #'(lambda (k e) (unless (gh-cache-expired-p e) (remhash k table))) table) (pcache-save cache))) (defmethod gh-cache-outdated-p ((cache gh-cache) key) (let* ((table (oref cache :entries)) (entry (gethash key table))) (and entry (oref entry :outdated)))) (defmethod gh-cache-expired-p ((cache gh-cache) key) (let* ((table (oref cache :entries)) (entry (gethash key table))) (and (gh-cache-outdated-p cache key) (not (let ((time (float-time (current-time)))) (< time (+ gh-cache-outdated-expiration-delay (oref entry :timestamp)))))))) (defmethod gh-cache-revive ((cache gh-cache) key) (let* ((table (oref cache :entries)) (entry (gethash key table))) (and entry (oset entry :outdated nil) (oset entry :timestamp (float-time (current-time))) t))) (defmethod gh-cache-etag ((cache gh-cache) key) (let* ((table (oref cache :entries)) (entry (gethash key table))) (and entry (oref entry :etag)))) (defmethod gh-cache-set-etag ((cache gh-cache) key etag) (let* ((table (oref cache :entries)) (entry (gethash key table))) (and entry (oset entry :etag etag)))) (provide 'gh-cache) ;;; gh-cache.el ends here ;; Local Variables: ;; indent-tabs-mode: nil ;; End: