31 using namespace basis;
44 auto_synchronizer l(*_ent_lock)
47 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
68 : _item(item), _id(
id), _when_added() {}
70 ~infoton_holder() {
WHACK(_item); }
82 class entity_basket :
public amorph<infoton_holder>
89 for (
int i = 0; i < elements(); i++)
90 to_return += get(i)->
text_form() + parser_bits::platform_eol_to_chars();
103 octopus_entity *key = (octopus_entity *)key_data;
107 + (key->add_in() << 10)
108 + (key->sequencer() << 14)
109 + (key->hostname()[0] << 20)
110 + (key->hostname()[1] << 24) );
116 class entity_item_hash
117 :
public hash_table<octopus_entity, entity_basket>
120 entity_item_hash(
const entity_hasher &hash)
137 basketcase *_empty_baskets;
138 entity_basket *_any_item;
142 apply_struct(
int &items_held)
144 _decay_interval(0) {}
149 entity_data_bin::entity_data_bin(
int max_size_per_entity)
150 : _table(new entity_item_hash(entity_hasher())),
151 _ent_lock(new
mutex),
153 _max_per_ent(max_size_per_entity),
166 return _table->elements();
169 struct text_form_accumulator {
astring _accum; };
174 text_form_accumulator *shuttle = (text_form_accumulator *)data_link;
175 shuttle->_accum += bask.text_form();
182 text_form_accumulator shuttle;
184 return shuttle._accum;
190 #undef static_class_name
191 #define static_class_name() "entity_data_bin"
193 int *county = (
int *)data_link;
194 *county += bask.elements();
196 #undef static_class_name
201 int entity_data_bin::scramble_counter()
209 #ifdef DEBUG_ENTITY_DATA_BIN
211 if ( !(_action_count++ % 100) ) { \
212 int items = scramble_counter(); \
213 LOG(a_sprintf("-> %d items counted.", items)); \
225 infoton_holder *holder =
new infoton_holder(orig_id, to_add);
228 entity_basket *bask = _table->find(orig_id.
_entity);
231 bask =
new entity_basket;
232 _table->add(orig_id.
_entity, bask);
238 int current_size = 0;
239 for (
int i = 0; i < bask->elements(); i++)
240 current_size += bask->borrow(i)->_item->packed_size();
242 if (current_size + to_add->
packed_size() > _max_per_ent) {
244 LOG(
astring(
"size limit would be exceeded if we stored this product"));
249 bask->append(holder);
257 #define static_class_name() "entity_data_bin"
259 apply_struct *apple = (apply_struct *)data_link;
261 if (!bask.elements()) {
267 apple->_any_item = &bask;
269 #undef static_class_name
276 apply_struct apple(_items_held);
281 infoton_holder *found = apple._any_item->acquire(0);
282 apple._any_item->zap(0, 0);
283 if (!apple._any_item->elements()) {
285 #ifdef DEBUG_ENTITY_DATA_BIN
286 LOG(
astring(
"tossing empty basket ") + found->_id._entity.mangled_form());
288 _table->zap(found->_id._entity);
291 infoton *to_return = found->_item;
298 LOG(
"logic error: number of items went below zero.");
306 FUNCDEF(
"acquire_for_entity [multiple]");
310 if (maximum_size <= 0) maximum_size = 20 *
KILOBYTE;
314 while (maximum_size > 0) {
328 FUNCDEF(
"acquire_for_entity [single]");
332 entity_basket *bask = _table->find(requester);
336 if (!bask->elements()) {
337 #ifdef DEBUG_ENTITY_DATA_BIN
340 _table->zap(requester);
344 id = bask->get(0)->_id;
345 to_return = bask->borrow(0)->_item;
348 if (!bask->elements()) {
349 #ifdef DEBUG_ENTITY_DATA_BIN
352 _table->zap(requester);
357 LOG(
"logic error: number of items went below zero.");
364 FUNCDEF(
"acquire_for_identifier");
367 entity_basket *bask = _table->find(
id._entity);
369 if (!bask->elements()) {
370 #ifdef DEBUG_ENTITY_DATA_BIN
371 LOG(
astring(
"tossing empty basket ") +
id._entity.mangled_form());
373 _table->zap(
id._entity);
376 for (
int i = 0; i < bask->elements(); i++) {
377 if (bask->get(i)->_id ==
id) {
378 to_return = bask->borrow(i)->_item;
382 if (!bask->elements()) {
383 #ifdef DEBUG_ENTITY_DATA_BIN
384 LOG(
astring(
"tossing empty basket ") +
id._entity.mangled_form());
386 _table->zap(
id._entity);
391 LOG(
"logic error: number of items went below zero.");
402 #define static_class_name() "entity_data_bin"
404 apply_struct *apple = (apply_struct *)data_link;
405 time_stamp expiration_time(-apple->_decay_interval);
408 for (
int i = 0; i < bask.elements(); i++) {
409 infoton_holder &rec = *bask.borrow(i);
410 if (rec._when_added <= expiration_time) {
412 #ifdef DEBUG_ENTITY_DATA_BIN
416 apple->_items_held--;
418 if (apple->_items_held < 0)
419 LOG(
"logic error: number of items went below zero.");
431 #ifdef DEBUG_ENTITY_DATA_BIN
433 LOG(
a_sprintf(
"==> whacked %d old items.", whack_count));
435 if (!bask.elements()) {
439 *apple->_empty_baskets += key;
445 #undef static_class_name
450 #ifdef DEBUG_ENTITY_DATA_BIN
455 apply_struct apple(_items_held);
456 basketcase empty_baskets;
457 apple._empty_baskets = &empty_baskets;
458 apple._decay_interval = decay_interval;
462 for (
int i = empty_baskets.length() - 1; i >= 0; i--) {
463 #ifdef DEBUG_ENTITY_DATA_BIN
464 LOG(
astring(
"removing basket ") + empty_baskets.
get(i).mangled_form());
466 _table->zap(empty_baskets.get(i));
467 empty_baskets.zap(i, i);
479 entity_basket *bask = _table->find(
id);
480 if (!bask || !bask->elements())
return false;
481 items = bask->elements();
482 for (
int i = 0; i < bask->elements(); i++)
483 bytes += bask->borrow(i)->_item->packed_size();
a_sprintf is a specialization of astring that provides printf style support.
Provides a dynamically resizable ASCII character string.
virtual char get(int index) const
a constant peek at the string's internals at the specified index.
virtual void text_form(base_string &state_fill) const
Provides a text view of all the important info owned by this object.
virtual ~entity_data_bin()
bool add_item(infoton *to_add, const octopus_request_id &id)
infoton * acquire_for_any(octopus_request_id &id)
infoton * acquire_for_identifier(const octopus_request_id &id)
void clean_out_deadwood(int decay_interval=4 *basis::MINUTE_ms)
basis::astring text_form() const
bool get_sizes(const octopus_entity &id, int &items, int &bytes)
infoton * acquire_for_entity(const octopus_entity &requester, octopus_request_id &id)
implements a list of waiting infotons.
a list of pending requests and who made them.
An infoton is an individual request parcel with accompanying information.
virtual void text_form(basis::base_string &state_fill) const =0
requires derived infotons to be able to show their state as a string.
virtual int packed_size() const =0
reports how large the infoton will be when packed.
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.
basis::astring text_form() const
human readable form of the request.
octopus_entity _entity
the entity.
basis::outcome append(const contents *data)
puts "data" on the end of this amorph.
void reset()
cleans out all of the contents.
Implements hashing into buckets for quick object access.
A hashing algorithm takes a key and derives a related integer from it.
Emulates a mathematical set, providing several standard set operations.
basis::astring text_form() const
A synonym for the text_format() method.
Represents a point in time relative to the operating system startup time.
basis::astring text_form(stamp_display_style style=STAMP_RELATIVE) const
returns a simple textual representation of the time_stamp.
#define formal(parameter)
This macro just eats what it's passed; it marks unused formal parameters.
#define NULL_POINTER
The value representing a pointer to nothing.
#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.
unsigned int un_int
Abbreviated name for unsigned integers.
const int KILOBYTE
Number of bytes in a kilobyte.
A logger that sends to the console screen using the standard output device.
bool text_form_applier(const octopus_entity &formal(key), entity_basket &bask, void *data_link)
bool cleaning_applier(const octopus_entity &key, entity_basket &bask, void *data_link)
const int OCTOPUS_TABLE_BITS
bool scramble_applier(const octopus_entity &formal(key), entity_basket &bask, void *data_link)
bool any_item_applier(const octopus_entity &formal(key), entity_basket &bask, void *data_link)
A dynamic container class that holds any kind of object via pointers.