feisty meow concerns codebase  2.140
list_manager.cpp
Go to the documentation of this file.
1 /*****************************************************************************\
2 * *
3 * Name : list_manager *
4 * Author : Chris Koeritz *
5 * *
6 *******************************************************************************
7 * Copyright (c) 2002-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
14 
15 #include "bundle_list.h"
16 #include "list_manager.h"
17 
18 #include <basis/astring.h>
19 #include <basis/functions.h>
20 #include <basis/mutex.h>
22 
23 using namespace basis;
24 using namespace octopi;
25 using namespace structures;
26 using namespace timely;
27 
28 namespace synchronic {
29 
30 //#define DEBUG_LIST_MANAGER
31  // uncomment for noisier version.
32 
33 #undef GRAB_LOCK
34 #define GRAB_LOCK \
35  auto_synchronizer l(*_locking)
36 
37 #undef LOG
38 #define LOG(to_print) \
39  CLASS_EMERGENCY_LOG(program_wide_logger::get(), to_print)
40 
41 list_manager::list_manager(const string_array &list_name, bool backgrounded)
42 : tentacle(list_name, backgrounded),
43  _entries(new bundle_list),
44  _locking(new mutex)
45 {
46 }
47 
49 {
50  WHACK(_entries);
51  WHACK(_locking);
52 }
53 
54 const string_array &list_manager::list_name() const { return group(); }
55 
57 {
58  GRAB_LOCK;
59  return _entries->elements();
60 }
61 
63 {
64  GRAB_LOCK;
65  _entries->zap(0, _entries->elements() - 1);
66 }
67 
68 bool list_manager::is_listed(const string_array &classifier)
69 {
70  GRAB_LOCK;
71  int indy = locked_find(classifier);
72  return !negative(indy);
73 }
74 
75 bool list_manager::update(const string_array &classifier, int offset)
76 {
77  GRAB_LOCK;
78  int indy = locked_find(classifier);
79  if (negative(indy)) return false; // not found.
80  _entries->borrow(indy)->_updated = time_stamp(offset);
81  return true;
82 }
83 
84 void list_manager::clean(int older_than)
85 {
86  GRAB_LOCK;
87  for (int i = 0; i < _entries->elements(); i++) {
88  synchronizable *curr = _entries->borrow(i);
89  if (curr->_updated < time_stamp(-older_than)) {
90  // this one is too old to keep around.
91  _entries->zap(i, i);
92  i--; // skip back before deleted item.
93  }
94  }
95 }
96 
97 bool list_manager::zap(const string_array &classifier)
98 {
99  GRAB_LOCK;
100  int indy = locked_find(classifier);
101  if (negative(indy)) return false; // not found.
102  _entries->zap(indy, indy);
103  return true; // did find and whack it.
104 }
105 
106 int list_manager::locked_find(const string_array &classifier)
107 {
108  for (int i = 0; i < _entries->elements(); i++) {
109  // check that the classifier lengths are equal; otherwise no match.
110  if (_entries->get(i)->classifier().length() != classifier.length())
111  continue;
112  // starting from the end of most significance, we compare the strings.
113  // we don't want to bother comparing the end that's most likely to be
114  // the same for items in the list (the front, that is).
115  bool problems = false;
116  for (int j = classifier.length() - 1; j >= 0; j--) {
117  if (_entries->get(i)->classifier()[j] != classifier[j]) {
118  problems = true;
119  break; // get out now since we're hosed.
120  }
121  }
122  if (problems) continue; // nope, there was a mismatch.
123  // success; this guy matches.
124  return i;
125  }
126  return common::NOT_FOUND; // not found.
127 }
128 
130 {
131  GRAB_LOCK;
132  int indy = locked_find(classifier);
133  if (negative(indy)) return NULL_POINTER;
134  return dynamic_cast<synchronizable *>(_entries->get(indy)->clone());
135 }
136 
138 {
139  to_fill.reset();
140  GRAB_LOCK;
141  for (int i = 0; i < _entries->elements(); i++)
142  to_fill += dynamic_cast<synchronizable *>(_entries->get(i)->clone());
143 }
144 
146  const octopus_request_id &formal(item_id), byte_array &transformed)
147 {
148 #ifdef DEBUG_LIST_MANAGER
149  FUNCDEF("consume");
150 #endif
151  transformed.reset();
152  synchronizable *bun = dynamic_cast<synchronizable *>(&to_chow);
153  if (!bun) return BAD_INPUT;
154 
155  GRAB_LOCK;
156 
157  // now perform an appropriate action depending on the type of update.
158  switch (bun->_mod) {
161  // see if the item already exists; if it does, overwrite it.
162  int indy = locked_find(bun->classifier());
163  if (negative(indy)) {
164  // the item is new, so just drop it in the list.
165  *_entries += dynamic_cast<synchronizable *>(bun->clone());
166  } else {
167  // not a new item, so merge with the existing contents.
168  _entries->borrow(indy)->merge(*bun);
169  _entries->borrow(indy)->_updated = time_stamp();
170  }
171  return OKAY;
172  }
174  int indy = locked_find(bun->classifier());
175  if (non_negative(indy)) {
176  // found it, so whack the entry as needed by calling merge.
177  outcome ret = _entries->borrow(indy)->merge(*bun);
178  _entries->borrow(indy)->_updated = time_stamp();
179  if (ret == synchronizable::EMPTY) {
180  // they have told us that this must go now.
181 #ifdef DEBUG_LIST_MANAGER
182  LOG(astring("removing entry now due to merge outcome: ")
183  + _entries->borrow(indy)->text_form());
184 #endif
185  _entries->zap(indy, indy);
186  }
187  return OKAY;
188  } else {
189  // that item was not listed.
190 #ifdef DEBUG_LIST_MANAGER
191  LOG(astring("could not find entry for ") + bun->text_form());
192 #endif
193  return NOT_FOUND;
194  }
195  break;
196  }
197  default: return NO_HANDLER;
198  }
199  return OKAY;
200 }
201 
203 {
204  FUNCDEF("expunge");
205 }
206 
207 } //namespace.
208 
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition: array.h:349
int length() const
Returns the current reported length of the allocated C array.
Definition: array.h:115
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
A very common template for a dynamic array of bytes.
Definition: byte_array.h:36
Outcomes describe the state of completion for an operation.
Definition: outcome.h:31
An infoton is an individual request parcel with accompanying information.
Definition: infoton.h:32
const structures::string_array & classifier() const
this array of strings is the "name" for this infoton.
Definition: infoton.cpp:85
Provides a way of identifying users of an octopus object.
Definition: entity_defs.h:35
Identifies requests made on an octopus by users.
Definition: entity_defs.h:114
Manages a service within an octopus by processing certain infotons.
Definition: tentacle.h:36
const structures::string_array & group() const
returns the name of the group that this tentacle services.
Definition: tentacle.cpp:96
@ NO_HANDLER
no handler for that type of infoton.
Definition: tentacle.h:73
int elements() const
the maximum number of elements currently allowed in this amorph.
Definition: amorph.h:66
basis::outcome zap(int start, int end)
Removes a range of indices from the amorph.
Definition: amorph.h:357
void reset()
cleans out all of the contents.
Definition: amorph.h:81
const contents * get(int field) const
Returns a constant pointer to the information at the index "field".
Definition: amorph.h:312
contents * borrow(int field)
Returns a pointer to the information at the index "field".
Definition: amorph.h:448
An array of strings with some additional helpful methods.
Definition: string_array.h:32
Provides a structure for managing a collection of synchronizables.
Definition: bundle_list.h:26
bool zap(const structures::string_array &classifier)
void retrieve(bundle_list &to_fill) const
bool update(const structures::string_array &classifier, int offset=0)
virtual void expunge(const octopi::octopus_entity &to_remove)
called to remove traces of the entity "to_remove".
void clean(int older_than)
bool is_listed(const structures::string_array &classifier)
virtual basis::outcome consume(octopi::infoton &to_chow, const octopi::octopus_request_id &item_id, basis::byte_array &transformed)
this is the main function that processes infotons for this tentacle.
const structures::string_array & list_name() const
synchronizable * clone_object(const structures::string_array &classifier)
Encapsulates all of the attributes known for an object.
virtual basis::astring text_form() const =0
local version just makes text_form() more functional.
virtual clonable * clone() const =0
must be provided to allow creation of a copy of this object.
timely::time_stamp _updated
Represents a point in time relative to the operating system startup time.
Definition: time_stamp.h:38
#define formal(parameter)
This macro just eats what it's passed; it marks unused formal parameters.
Definition: definitions.h:48
#define NULL_POINTER
The value representing a pointer to nothing.
Definition: definitions.h:32
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
#define GRAB_LOCK
#define LOG(to_print)
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition: functions.h:121
bool non_negative(const type &a)
non_negative returns true if "a" is greater than or equal to zero.
Definition: functions.h:45
bool negative(const type &a)
negative returns true if "a" is less than zero.
Definition: functions.h:43
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#include <time.h>
Definition: earth_time.cpp:37