first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / octopi / library / octopus / tentacle.h
1 #ifndef TENTACLE_CLASS
2 #define TENTACLE_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : tentacle                                                          *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 2002-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 #include <basis/byte_array.h>
19 #include <basis/mutex.h>
20 #include <structures/string_array.h>
21
22 namespace octopi {
23
24 // forward.
25 class entity_data_bin;
26 class infoton;
27 class octopus;
28 class octopus_entity;
29 class octopus_request_id;
30 class pod_motivator;
31 class queueton;
32
33 //! Manages a service within an octopus by processing certain infotons.
34
35 class tentacle : public virtual basis::root_object
36 {
37 public:
38   tentacle(const structures::string_array &group_name, bool backgrounded,
39           int motivational_rate = tentacle::DEFAULT_RATE);
40     //!< constructs a tentacle that handles infotons with the "group_name".
41     /*!< if "backgrounded" is true, then the tentacle will periodically look
42     for queued requests at the specified "motivational_rate".  if
43     "backgrounded" is false, then the tentacle will not perform any background
44     processing, meaning that it can only provide immediate evaluation for an
45     octopus. */
46
47   virtual ~tentacle();
48
49   enum constants { DEFAULT_RATE = 40 };
50
51   DEFINE_CLASS_NAME("tentacle");
52
53   const structures::string_array &group() const;
54     //!< returns the name of the group that this tentacle services.
55     /*!< this can be a single string or it can be a list of names.  a tentacle
56     can only service one name group currently. */
57
58   bool backgrounding() const { return _backgrounded; }
59     //!< reports on whether this tentacle supports background operation or not.
60
61   int motivational_rate() const;
62     //!< returns the background processing rate this was constructed with.
63
64   enum outcomes {
65     OKAY = basis::common::OKAY,
66     NOT_FOUND = basis::common::NOT_FOUND,
67     ALREADY_EXISTS = basis::common::EXISTING,
68     BAD_INPUT = basis::common::BAD_INPUT,
69     NO_SPACE = basis::common::NO_SPACE,
70     GARBAGE = basis::common::GARBAGE,
71     DISALLOWED = basis::common::DISALLOWED,
72
73     NO_HANDLER = basis::common::NO_HANDLER,  //!< no handler for that type of infoton.
74     PARTIAL = basis::common::PARTIAL,  //!< processing of request is partially done.
75     ENCRYPTION_MISMATCH = basis::common::ENCRYPTION_MISMATCH
76       //!< there is a disconnect regarding encryption.
77   };
78
79   static const char *outcome_name(const basis::outcome &to_name);
80     //!< returns the textual form of the outcome "to_name".
81
82   //////////////
83
84   // functions that must be provided by derived tentacles.
85
86   virtual basis::outcome reconstitute(const structures::string_array &classifier,
87           basis::byte_array &packed_form, infoton * &reformed) = 0;
88     //!< regenerates an infoton from its packed form.
89     /*!< given the "classifier" under which the object is categorized, this
90     reconstructs a "reformed" infoton equivalent to the flattened infoton
91     in "packed_form".  the "packed_form" is destructively consumed.
92     NOTE: it is crucial that the derived method calls set_classifier() on
93     the "reformed" infoton from the passed "classifier". */
94
95   virtual basis::outcome consume(infoton &to_chow, const octopus_request_id &item_id,
96           basis::byte_array &transformed) = 0;
97     //!< this is the main function that processes infotons for this tentacle.
98     /*!< the octopus will feed this function with appropriate data "to_chow"
99     for infotons that are to be processed by this tentacle's group().  the
100     "item_id" provides for the requesting entity an origination marker that
101     can be used in produce() below.  the outcome indicates whether the
102     processing was successful.  processing could fail due to a missing
103     handler for the item, due to erronous data in the infoton, because of
104     resource limits placed on the tentacle, from explicit rejection by the
105     tentacle, or due to other causes.  the "transformed" is a packed infoton
106     that may be generated during the consumption of "to_chow" (it must
107     actually be a packed classifier and then the packed infoton).  if it can
108     be unpacked successfully, then it will be treated as the actual infoton
109     that was to be consumed.  this is only expected from a filter.
110     note: the infoton "to_chow" can be destructively manipulated by the
111     tentacle, including patching the classifier for internal octopi or
112     rearranging any data contained in "to_chow".  none of these changes
113     will be seen by the entity that requested processing.
114     regarding filters: if this tentacle is serving as a filter, then it
115     may be presented with infotons that are not covered by its group.
116     given such an infoton, the tentacle should perform whatever filtering
117     is to be done, including modifying the infoton appropriately, and
118     return PARTIAL when it liked the infoton or DISALLOWED when it
119     rejects the infoton.  it is understood that the infoton will be
120     passed along to the rest of the tentacles when the successful
121     result of PARTIAL is returned. */
122
123   virtual void expunge(const octopus_entity &to_remove) = 0;
124     //!< called to remove traces of the entity "to_remove".
125     /*!< this is an order from the octopus that all traces of the entity
126     "to_remove" should now be cleaned out.  that entity has been utterly
127     destroyed and any data structures held for it should be thrown out
128     also.  the required actions are specific to the tentacle's design. */
129
130   //////////////
131
132   basis::outcome enqueue(infoton *to_chow, const octopus_request_id &item_id);
133     //!< holds onto infotons coming from the octopus for backgrounding.
134     /*!< this will add an infoton "to_chow" into the list of objects to be
135     consumed.  at some point after a successful outcome from this, the
136     tentacle will be handed the infoton for processing.  NOTE: all
137     responsibility for the infoton "to_chow" is passed to this method; the
138     infoton should not be touched in any way after invocation. */
139
140   infoton *next_request(octopus_request_id &item_id);
141     //!< pops out the next queued request for processing.
142     /*!< this function locates the next request for the tentacle when it is
143     in its consume() method.  the returned infoton was previously passed
144     to the enqueue() method and needs to be processed.  if there are no
145     requests ready, NIL is returned. */
146
147   bool store_product(infoton *product, const octopus_request_id &original_id);
148     //!< used by tentacles to store the objects they produce from infotons.
149     /*!< this will cache the "product" object and its "original_id" for later
150     retrieval from the entity_data_bin we were given when hooked to an octopus.
151     note that the "product" must be allocated dynamically and that it becomes
152     owned by the response bin after this call (do not delete the original
153     pointer).  if the item would not fit in the entity's bin, then false is
154     returned and the "product" is deleted. */
155
156   //////////////
157
158   // support that is for internal use only.
159
160   void attach_storage(entity_data_bin &storage);
161     //!< used when a tentacle is being integrated with an octopus.
162     /*!< not for casual external users.  note that the tentacle's background
163     processing will not be started until attach is called and that it stops
164     when detach is called. */
165   void detach_storage();
166     //!< unhooks the storage bin from this tentacle.
167
168   void propel_arm();
169     //!< invoked by our thread to cause requests to be processed.
170  
171 private:
172   structures::string_array *_group;  //!< the group name that this tentacle handles.
173   queueton *_pending;  //!< the requests that are waiting fulfillment.
174   basis::mutex *_input_guard;  //!< protects the incoming requests.
175   pod_motivator *_action;  //!< the thread that keeps things moving along.
176   entity_data_bin *_products;  //!< if non-nil, where we store responses.
177   bool _backgrounded;  //!< records whether we're threading or not.
178
179   // not permitted.
180   tentacle(const tentacle &);
181   tentacle &operator =(const tentacle &);
182 };
183
184 } //namespace.
185
186 #endif
187