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_count = 0;
int current_size = 0;
240 #ifdef DEBUG_ENTITY_DATA_BIN
243 if (current_size +
to_add->packed_size() > _max_per_ent) {
244 #ifdef DEBUG_ENTITY_DATA_BIN
245 LOG(
a_sprintf(
"size limit would be exceeded if we stored this product (would grow to %d with limit of %d).", current_size +
to_add->packed_size(), _max_per_ent));
252 bask->append(holder);
255 #ifdef DEBUG_ENTITY_DATA_BIN
266 #define static_class_name() "entity_data_bin"
268 apply_struct *apple = (apply_struct *)data_link;
270 if (!bask.elements()) {
276 apple->_any_item = &bask;
278 #undef static_class_name
285 apply_struct apple(_items_held);
289 #ifdef DEBUG_ENTITY_DATA_BIN
296 infoton_holder *found = apple._any_item->acquire(0);
297 apple._any_item->zap(0, 0);
298 if (!apple._any_item->elements()) {
300 #ifdef DEBUG_ENTITY_DATA_BIN
301 LOG(
astring(
"tossing empty basket ") + found->_id._entity.mangled_form());
303 _table->zap(found->_id._entity);
306 infoton *to_return = found->_item;
314 LOG(
"logic error: number of items went below zero.");
317 #ifdef DEBUG_ENTITY_DATA_BIN
327 FUNCDEF(
"acquire_for_entity [multiple]");
331 if (maximum_size <= 0) maximum_size = 20 *
KILOBYTE;
335 while (maximum_size > 0) {
349 FUNCDEF(
"acquire_for_entity [single]");
353 entity_basket *bask = _table->find(requester);
357 if (!bask->elements()) {
358 #ifdef DEBUG_ENTITY_DATA_BIN
361 _table->zap(requester);
365 id = bask->get(0)->_id;
366 to_return = bask->borrow(0)->_item;
369 if (!bask->elements()) {
370 #ifdef DEBUG_ENTITY_DATA_BIN
373 _table->zap(requester);
378 LOG(
"logic error: number of items went below zero.");
385 FUNCDEF(
"acquire_for_identifier");
388 entity_basket *bask = _table->find(
id._entity);
390 if (!bask->elements()) {
391 #ifdef DEBUG_ENTITY_DATA_BIN
392 LOG(
astring(
"tossing empty basket ") +
id._entity.mangled_form());
394 _table->zap(
id._entity);
397 for (
int i = 0; i < bask->elements(); i++) {
398 if (bask->get(i)->_id ==
id) {
399 to_return = bask->borrow(i)->_item;
403 if (!bask->elements()) {
404 #ifdef DEBUG_ENTITY_DATA_BIN
405 LOG(
astring(
"tossing empty basket ") +
id._entity.mangled_form());
407 _table->zap(
id._entity);
412 LOG(
"logic error: number of items went below zero.");
423 #define static_class_name() "entity_data_bin"
425 apply_struct *apple = (apply_struct *)data_link;
426 time_stamp expiration_time(-apple->_decay_interval);
429 for (
int i = 0; i < bask.elements(); i++) {
430 infoton_holder &rec = *bask.borrow(i);
431 if (rec._when_added <= expiration_time) {
433 #ifdef DEBUG_ENTITY_DATA_BIN
437 apple->_items_held--;
439 if (apple->_items_held < 0)
440 LOG(
"logic error: number of items went below zero.");
452 #ifdef DEBUG_ENTITY_DATA_BIN
454 LOG(
a_sprintf(
"==> whacked %d old items.", whack_count));
456 if (!bask.elements()) {
460 *apple->_empty_baskets += key;
466 #undef static_class_name
471 #ifdef DEBUG_ENTITY_DATA_BIN
476 apply_struct apple(_items_held);
477 basketcase empty_baskets;
478 apple._empty_baskets = &empty_baskets;
479 apple._decay_interval = decay_interval;
483 for (
int i = empty_baskets.length() - 1; i >= 0; i--) {
484 #ifdef DEBUG_ENTITY_DATA_BIN
485 LOG(
astring(
"removing basket ") + empty_baskets.
get(i).mangled_form());
487 _table->zap(empty_baskets.get(i));
488 empty_baskets.zap(i, i);
499 entity_basket *bask = _table->find(
id);
500 if (!bask || !bask->elements())
return false;
501 items = bask->elements();
502 for (
int i = 0; i < bask->elements(); i++)
503 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) const
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.