34 using namespace basis;
51 auto_synchronizer l(*_molock)
57 #define WHACK_RETURN(to_ret, to_whack) { \
58 unhandled_request *bad_response = new unhandled_request(id, \
59 request->classifier(), to_ret); \
60 _responses->add_item(bad_response, id); \
69 #define LOG(t) CLASS_EMERGENCY_LOG(program_wide_logger::get(), t)
78 class filter_list :
public array<tentacle *>
82 for (
int i = 0; i < length(); i++) {
83 if (get(i) == to_remove) {
100 tentacle_record(tentacle *limb,
bool filter)
101 : _limb(limb), _filter(filter) {}
103 ~tentacle_record() {
WHACK(_limb); }
108 class modula_oblongata :
public amorph<tentacle_record>
111 modula_oblongata() :
amorph<tentacle_record>() {}
114 for (
int i = 0; i < elements(); i++) {
115 if (borrow(i)->_limb->group().prefix_compare(group))
118 return common::NOT_FOUND;
122 int indy = find_index(group);
124 return borrow(indy)->_limb;
127 bool zap(
int a,
int b) {
129 return ret == common::OKAY;
133 int indy = find_index(group);
142 octopus::octopus(
const astring &name,
int max_per_ent)
144 _tentacles(new modula_oblongata),
147 _disallow_removals(0),
149 _clean_lock(new
mutex),
150 _filters(new filter_list),
166 WHACK(_next_cleaning);
185 {
return _tentacles->borrow(indy)->_limb; }
206 _disallow_removals++;
211 int len = _tentacles->elements();
212 for (
int i = 0; i < len; i++) {
213 tentacle_record *curr = _tentacles->borrow(i);
214 if (!curr || !curr->_limb) {
219 curr->_limb->expunge(to_remove);
225 _disallow_removals--;
231 while (items_found) {
238 LOG(
a_sprintf(
"cleaned %d items for expunged entity ", items_found)
270 tentacle_record *new_record =
new tentacle_record(to_add, filter);
271 _tentacles->append(new_record);
272 if (filter) *_filters += to_add;
289 if (!_disallow_removals) {
294 if (_disallow_removals < 0) {
296 "reference counter.");
299 time_control::sleep_ms(0);
301 int indy = _tentacles->find_index(group_name);
308 tentacle_record *freeing = _tentacles->acquire(indy);
309 _tentacles->zap(indy, indy);
310 free_me = freeing->_limb;
311 _filters->remove(free_me);
333 _disallow_removals++;
335 tentacle *found = _tentacles->find(classifier);
343 to_return = found->
reconstitute(classifier, packed_form, reformed);
347 _disallow_removals--;
360 LOG(
"failed due to empty classifier.");
368 _disallow_removals++;
371 for (
int i = 0; i < _filters->length(); i++) {
373 #ifdef DEBUG_OCTOPUS_FILTERS
380 #ifdef DEBUG_OCTOPUS_FILTERS
382 LOG(
astring(
"found it to be relevant! for ") +
id.text_form())
384 LOG(
astring(
"found it to not be relevant. for ") +
id.text_form());
399 #ifdef DEBUG_OCTOPUS_FILTERS
401 "infoton from " +
id.
text_form() +
" with result "
406 _disallow_removals--;
410 #ifdef DEBUG_OCTOPUS_FILTERS
412 "infoton " +
id.
text_form() +
" with result "
420 if (transformed.
length()) {
426 LOG(
"failed to fast_unpack the transformed data.");
435 LOG(
"failed to restore transformed infoton.");
444 #ifdef DEBUG_OCTOPUS_FILTERS
450 _disallow_removals--;
459 #ifdef DEBUG_OCTOPUS_FILTERS
460 LOG(
astring(
"all filters approved infoton: ") +
id.text_form());
476 _disallow_removals--;
485 _disallow_removals--;
493 _disallow_removals--;
504 next_time = *_next_cleaning;
519 tentacle *found = _tentacles->find(tentacle_name);
a_sprintf is a specialization of astring that provides printf style support.
Represents a sequential, ordered, contiguous collection of objects.
int length() const
Returns the current reported length of the allocated C array.
Provides a dynamically resizable ASCII character string.
virtual void text_form(base_string &state_fill) const
Provides a text view of all the important info owned by this object.
auto_synchronizer simplifies concurrent code by automatically unlocking.
A very common template for a dynamic array of bytes.
void lock()
Clamps down on the mutex, if possible.
void unlock()
Gives up the possession of the mutex.
Outcomes describe the state of completion for an operation.
a platform-independent way to acquire random numbers in a specific range.
int inclusive(int low, int high) const
< Returns a pseudo-random number r, such that "low" <= r <= "high".
Stores a set of infotons grouped by the entity that owns them.
infoton * acquire_for_identifier(const octopus_request_id &id)
void clean_out_deadwood(int decay_interval=4 *basis::MINUTE_ms)
infoton * acquire_for_entity(const octopus_entity &requester, octopus_request_id &id)
Supports an early step in using octopus services: getting an identity.
a list of pending requests and who made them.
An infoton is an individual request parcel with accompanying information.
static bool fast_unpack(basis::byte_array &packed_form, structures::string_array &classifier, basis::byte_array &info)
undoes a previous fast_pack to restore the previous information.
const structures::string_array & classifier() const
this array of strings is the "name" for this infoton.
Provides a way of identifying users of an octopus object.
basis::astring mangled_form() const
returns the combined string form of the identifier.
Identifies requests made on an octopus by users.
entity_data_bin & responses()
allows external access to our set of results.
tentacle * locked_get_tentacle(int indy)
access indy'th tentacle.
void unlock_tentacles()
unlocks the list.
basis::outcome add_tentacle(tentacle *to_add, bool filter=false)
hooks a tentacle in to provide processing of one type of infoton.
void periodic_cleaning()
flushes any abandoned data from the response bin.
tentacle * lock_tentacle(const structures::string_array &tentacle_name)
locates the tentacle with the "tentacle_name" and returns it.
int locked_tentacle_count()
number of tentacles.
infoton * acquire_result(const octopus_entity &requester, octopus_request_id &original_id)
acquires responses to previous requests if there are any waiting.
basis::outcome evaluate(infoton *request, const octopus_request_id &item_id, bool now=false)
tries to process the "request" using the current set of tentacles.
void unlock_tentacle(tentacle *to_unlock)
unlocks the octopus when given a previously locked tentacle.
octopus_entity issue_identity()
creates an entity identifier that is unique for this octopus.
infoton * acquire_specific_result(const octopus_request_id &original_id)
supports seeking the result for a specific request.
basis::outcome restore(const structures::string_array &classifier, basis::byte_array &packed_form, infoton *&reformed)
regenerates a packed infoton given its classifier.
basis::outcome zap_tentacle(const structures::string_array &group_name)
similar to remove_tentacle(), but destroys the tentacle.
const basis::astring & name() const
returns the name that the octopus was constructed with.
void expunge(const octopus_entity &to_remove)
invokes every tentacle's expunge() method on the id "to_remove".
basis::outcome remove_tentacle(const structures::string_array &group_name, tentacle *&free_me)
removes the tentacle listed for the "group_name", if any.
void lock_tentacles()
locks the tentacle list for use with locked_get_tentacle.
Manages a service within an octopus by processing certain infotons.
virtual basis::outcome consume(infoton &to_chow, const octopus_request_id &item_id, basis::byte_array &transformed)=0
this is the main function that processes infotons for this tentacle.
basis::outcome enqueue(infoton *to_chow, const octopus_request_id &item_id)
holds onto infotons coming from the octopus for backgrounding.
bool backgrounding() const
reports on whether this tentacle supports background operation or not.
const structures::string_array & group() const
returns the name of the group that this tentacle services.
virtual basis::outcome reconstitute(const structures::string_array &classifier, basis::byte_array &packed_form, infoton *&reformed)=0
regenerates an infoton from its packed form.
static const char * outcome_name(const basis::outcome &to_name)
returns the textual form of the outcome "to_name".
@ PARTIAL
processing of request is partially done.
void attach_storage(entity_data_bin &storage)
used when a tentacle is being integrated with an octopus.
Implements a thread-safe roller object.
int next_id()
returns a unique (per instance of this type) id.
void reset()
cleans out all of the contents.
An array of strings with some additional helpful methods.
bool prefix_compare(const string_array &second) const
Returns true if all of the elements in this are the same in "second".
basis::astring text_form() const
A synonym for the text_format() method.
Represents a point in time relative to the operating system startup time.
void reset()
sets the stamp time back to now.
#define continuable_error(c, f, i)
#define NULL_POINTER
The value representing a pointer to nothing.
#define MAXINT32
Maximum 32-bit integer value.
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
The guards collection helps in testing preconditions and reporting errors.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
bool negative(const type &a)
negative returns true if "a" is less than zero.
const int MINUTE_ms
Number of milliseconds in a minute.
const int KILOBYTE
Number of bytes in a kilobyte.
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
const int MAXIMUM_TRASH_SIZE
const int OCTOPUS_CHECKING_INTERVAL
A dynamic container class that holds any kind of object via pointers.
time_locus now()
returns our current locus in the time continuum.
#define WHACK_RETURN(to_ret, to_whack)