00001 #ifndef LIST_MANAGER_IMPLEMENTATION_FILE
00002 #define LIST_MANAGER_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "bundle_list.h"
00019 #include "list_manager.h"
00020
00021 #include <basis/function.h>
00022 #include <basis/istring.h>
00023 #include <basis/log_base.h>
00024 #include <basis/mutex.h>
00025 #include <basis/string_array.h>
00026
00027
00028
00029
00030 #undef GRAB_LOCK
00031 #define GRAB_LOCK \
00032 auto_synchronizer l(*_locking)
00033
00034 #undef LOG
00035 #define LOG(to_print) \
00036 CLASS_EMERGENCY_LOG(program_wide_logger(), to_print)
00037
00038 list_manager::list_manager(const string_array &list_name, bool backgrounded)
00039 : tentacle(list_name, backgrounded),
00040 _entries(new bundle_list),
00041 _locking(new mutex)
00042 {
00043 }
00044
00045 list_manager::~list_manager()
00046 {
00047 WHACK(_entries);
00048 WHACK(_locking);
00049 }
00050
00051 const string_array &list_manager::list_name() const { return group(); }
00052
00053 int list_manager::entries() const
00054 {
00055 GRAB_LOCK;
00056 return _entries->elements();
00057 }
00058
00059 void list_manager::reset()
00060 {
00061 GRAB_LOCK;
00062 _entries->zap(0, _entries->elements() - 1);
00063 }
00064
00065 bool list_manager::is_listed(const string_array &classifier)
00066 {
00067 GRAB_LOCK;
00068 int indy = locked_find(classifier);
00069 return !negative(indy);
00070 }
00071
00072 bool list_manager::update(const string_array &classifier, int offset)
00073 {
00074 GRAB_LOCK;
00075 int indy = locked_find(classifier);
00076 if (negative(indy)) return false;
00077 _entries->borrow(indy)->_updated = time_stamp(offset);
00078 return true;
00079 }
00080
00081 void list_manager::clean(int older_than)
00082 {
00083 GRAB_LOCK;
00084 for (int i = 0; i < _entries->elements(); i++) {
00085 attribute_bundle *curr = _entries->borrow(i);
00086 if (curr->_updated < time_stamp(-older_than)) {
00087
00088 _entries->zap(i, i);
00089 i--;
00090 }
00091 }
00092 }
00093
00094 bool list_manager::zap(const string_array &classifier)
00095 {
00096 GRAB_LOCK;
00097 int indy = locked_find(classifier);
00098 if (negative(indy)) return false;
00099 _entries->zap(indy, indy);
00100 return true;
00101 }
00102
00103 int list_manager::locked_find(const string_array &classifier)
00104 {
00105 for (int i = 0; i < _entries->elements(); i++) {
00106
00107 if (_entries->get(i)->classifier().length() != classifier.length())
00108 continue;
00109
00110
00111
00112 bool problems = false;
00113 for (int j = classifier.length() - 1; j >= 0; j--) {
00114 if (_entries->get(i)->classifier()[j] != classifier[j]) {
00115 problems = true;
00116 break;
00117 }
00118 }
00119 if (problems) continue;
00120
00121 return i;
00122 }
00123 return common::NOT_FOUND;
00124 }
00125
00126 attribute_bundle *list_manager::clone_object(const string_array &classifier)
00127 {
00128 GRAB_LOCK;
00129 int indy = locked_find(classifier);
00130 if (negative(indy)) return NIL;
00131 return (attribute_bundle *)(*_entries)[indy]->clone();
00132 }
00133
00134 void list_manager::retrieve(bundle_list &to_fill) const
00135 {
00136 to_fill.reset();
00137 GRAB_LOCK;
00138 for (int i = 0; i < _entries->elements(); i++)
00139 to_fill += (attribute_bundle *)(*_entries)[i]->clone();
00140 }
00141
00142 outcome list_manager::consume(infoton &to_chow,
00143 const octopus_request_id &formal(item_id), byte_array &transformed)
00144 {
00145 FUNCDEF("consume");
00146 transformed.reset();
00147 attribute_bundle *bun = dynamic_cast<attribute_bundle *>(&to_chow);
00148 if (!bun) return BAD_INPUT;
00149
00150 GRAB_LOCK;
00151
00152
00153 switch (bun->_mod) {
00154 case attribute_bundle::ADDED:
00155 case attribute_bundle::CHANGED: {
00156
00157 int indy = locked_find(bun->classifier());
00158 if (negative(indy)) {
00159
00160 *_entries += (attribute_bundle *)bun->clone();
00161 } else {
00162
00163 _entries->borrow(indy)->merge(*bun);
00164 _entries->borrow(indy)->_updated = time_stamp();
00165 }
00166 return OKAY;
00167 }
00168 case attribute_bundle::DELETED: {
00169 int indy = locked_find(bun->classifier());
00170 if (non_negative(indy)) {
00171
00172 outcome ret = _entries->borrow(indy)->merge(*bun);
00173 _entries->borrow(indy)->_updated = time_stamp();
00174 if (ret == attribute_bundle::EMPTY) {
00175
00176 #ifdef DEBUG_LIST_MANAGER
00177 LOG(istring("removing entry now due to merge outcome: ")
00178 + _entries->borrow(indy)->text_form());
00179 #endif
00180 _entries->zap(indy, indy);
00181 }
00182 return OKAY;
00183 } else {
00184
00185 #ifdef DEBUG_LIST_MANAGER
00186 LOG(istring("could not find entry for ") + bun->text_form());
00187 #endif
00188 return NOT_FOUND;
00189 }
00190 break;
00191 }
00192 default: return NO_HANDLER;
00193 }
00194 return OKAY;
00195 }
00196
00197 void list_manager::expunge(const octopus_entity &formal(to_remove))
00198 {
00199 FUNCDEF("expunge");
00200 }
00201
00202
00203 #endif //LIST_MANAGER_IMPLEMENTATION_FILE
00204