servlib/prophet/Repository.h
changeset 0 2b3e5ec03512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/prophet/Repository.h	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,173 @@
+/*
+ *    Copyright 2007 Baylor University
+ * 
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ * 
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#ifndef _PROPHET_REPOSITORY_H_
+#define _PROPHET_REPOSITORY_H_
+
+#include "Bundle.h"
+#include "BundleList.h"
+#include "QueuePolicy.h"
+
+#if defined(__GNUC__)
+# define PRINTFLIKE(fmt, arg) __attribute__((format (printf, fmt, arg)))
+#else
+# define PRINTFLIKE(a, b)
+#endif
+
+namespace prophet
+{
+
+/**
+ * Implements a modified heap-based priority_queue with bounds enforcement.
+ * Any change to a Bundle's priority (such as the act of forwarding a Bundle
+ * over a link) requires a call-back to change_priority to preserve correct
+ * heap ordering.  Any change to a Bundle's size will result in undefined
+ * behavior; at present, the best practice is to drop() the bundle before
+ * the size change then add() it again after the size is finalized. Any
+ * change in policy (ie, a new comparator) will cost n for the pass-thru
+ * of reheaping; any change in max will also be at most a linear cost.
+ */
+class Repository
+{
+public:
+    typedef BundleList::iterator iterator;
+    typedef BundleList::const_iterator const_iterator;
+
+    /**
+     * Reduced interface into BundleCore to provide logging, drop_bundle
+     * signal, and answer the query for bundle storage quota
+     */
+    class BundleCoreRep
+    {
+    public:
+        virtual ~BundleCoreRep() {}
+        virtual void print_log(const char* name, int level,
+                               const char* fmt, ...)
+            PRINTFLIKE(4,5) = 0;
+        virtual void drop_bundle(const Bundle* bundle) = 0;
+        virtual u_int64_t max_bundle_quota() const = 0;
+    };
+
+    /**
+     * Constructor. Repository assumes ownership of memory pointed to by qc, 
+     * but not for list (makes a copy).
+     * @param core  facade interface into Bundle host
+     * @param qc	Queue Policy comparator to sort by eviction order (such
+     *              that the next Bundle to be evicted is evaluated less-than
+     *              all other Bundles)
+     * @param list	initial list of Bundles to store
+     */
+    Repository(BundleCoreRep* core, QueueComp* qc = NULL,
+               const BundleList* list = NULL);
+
+    /**
+     * Destructor
+     */
+    ~Repository();
+
+    /**
+     * Add bundle to Repository, incrementing current utilization by 
+     * Bundle's storage size.
+     * @param bundle	pointer to Bundle to be added
+     * @return whether bundle was added
+     */
+    bool add(const Bundle* bundle);
+
+    /**
+     * Remove arbitrary Bundle from Repository, and decrement current
+     * utilization accordingly. Assumes Bundle priority has not been
+     * changed, and that underlying heap is in priority order.
+     * @param bundle	pointer to Bundle to be removed
+     */
+    void del(const Bundle* bundle);
+
+    /**
+     * Change policy of Repository by replacing comparator; post condition
+     * is that eviction order is resorted using the new comparator.
+     * @param qc	comparator used to sort Bundles in eviction order 
+     */
+    void set_comparator(QueueComp* qc);
+
+    /**
+     * Accessor to current comparator
+     */
+    const QueueComp* get_comparator() const { return comp_; }
+
+    /**
+     * Callback to instruct Repository to query BundleCore on new max
+     */
+    void handle_change_max();
+
+    /**
+     * Callback for external notice to recalculate eviction order for
+     * list, due to changed comparator state
+     */
+    void change_priority(const Bundle* b);
+
+    /**
+     * Fetch const reference to internal list of Bundles (there is no
+     * guarantee of meaningful order to returned list)
+     */
+    const BundleList& get_bundles() const { return list_; }
+
+    /**
+     * Return boolean indicating whether Repository has any bundles.
+     */
+    bool empty() const { return list_.empty(); }
+
+    /**
+     * Return number of Bundles in Repository
+     */
+    size_t size() const { return list_.size(); }
+
+    /**
+     * Return the current upper limit imposed by Repository
+     */
+    u_int get_max() const { return core_->max_bundle_quota(); }
+
+    /**
+     * Return current storage consumed by Bundles in Repository
+     */
+    u_int get_current() const { return current_; }
+
+protected:
+    /**
+     * Evict the next candidate Bundle according to policy order
+     */
+    void evict();
+
+    ///@{ Heap operations
+    void make_heap(size_t first, size_t last);
+    void push_heap(size_t first, size_t hole, size_t top, const Bundle* b);
+    void pop_heap(size_t first, size_t last, size_t result, const Bundle* b);
+    void adjust_heap(size_t first, size_t hole, size_t len, const Bundle* b);
+    void remove_and_reheap(size_t hole);
+    ///@}
+
+    /**
+     * Utility function for find
+     */
+    bool find(const Bundle* b, iterator& i);
+
+    BundleCoreRep* core_; ///< facade interface into Bundle host
+    QueueComp* comp_; ///< queue policy Bundle comparator
+    BundleList list_; ///< array-based eviction-ordered heap of Bundles
+    u_int current_;   ///< current utilization
+}; // class Repository
+
+}; // namespace prophet
+
+#endif // _PROPHET_REPOSITORY_H_