first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / octopi / library / octopus / entity_defs.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : entity definitions for octopus                                    *
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 "entity_defs.h"
16
17 #include <configuration/application_configuration.h>
18 #include <mathematics/chaos.h>
19 #include <structures/amorph.h>
20 #include <structures/static_memory_gremlin.h>
21 #include <textual/byte_formatter.h>
22 #include <textual/parser_bits.h>
23 #include <textual/string_manipulation.h>
24
25 #include <stdio.h>  // for sscanf.
26
27 using namespace basis;
28 using namespace configuration;
29 using namespace mathematics;
30 using namespace textual;
31 using namespace structures;
32
33 namespace octopi {
34
35 octopus_entity::octopus_entity()
36 : _hostname(new astring),
37   _pid(0),
38   _sequencer(0),
39   _add_in(0)
40 {}
41
42 octopus_entity::octopus_entity(const astring &hostname,
43     int process_id, int sequencer, int add_in)
44 : _hostname(new astring(hostname)),
45   _pid(process_id),
46   _sequencer(sequencer),
47   _add_in(add_in)
48 {}
49
50 octopus_entity::octopus_entity(const octopus_entity &to_copy)
51 : packable(),
52   _hostname(new astring)
53 { operator = (to_copy); }
54
55 octopus_entity::~octopus_entity() { WHACK(_hostname); }
56
57 octopus_entity octopus_entity::from_text(const astring &to_convert)
58 {
59   astring host;
60   int process_id;
61   int sequencer;
62   int add_in;
63   breakout(to_convert, host, process_id, sequencer, add_in);
64
65   byte_array temp_form;
66   byte_formatter::string_to_bytes(host, temp_form);
67   host = astring((char *)temp_form.observe());
68
69   return octopus_entity(host, process_id, sequencer, add_in);
70 }
71
72 octopus_entity &octopus_entity::operator =(const octopus_entity &to_copy)
73 {
74   if (this == &to_copy) return *this;
75   *_hostname = *to_copy._hostname;
76   _pid = to_copy._pid;
77   _sequencer = to_copy._sequencer;
78   _add_in = to_copy._add_in;
79   return *this;
80 }
81
82 const astring &octopus_entity::hostname() const { return *_hostname; }
83
84 int octopus_entity::process_id() const { return _pid; }
85
86 int octopus_entity::sequencer() const { return _sequencer; }
87
88 int octopus_entity::add_in() const { return _add_in; }
89
90 void octopus_entity::process_id(int id) { _pid = id; }
91
92 void octopus_entity::sequencer(int seq) { _sequencer = seq; }
93
94 void octopus_entity::add_in(int add) { _add_in = add; }
95
96 void octopus_entity::hostname(const astring &new_host)
97 { *_hostname = new_host; }
98
99 bool octopus_entity::blank() const
100 { return !_sequencer && !_add_in && !_pid && _hostname->empty(); }
101
102 int octopus_entity::packed_size() const
103 { return sizeof(int) * 3 + _hostname->length() + 1; }
104
105 #define REPLACEMENT_CHARACTER '#'
106   // used to replace unprintable characters in the entity text_form().
107
108 astring octopus_entity::text_form() const
109 {
110   astring chewed_host = *_hostname;
111   // make sure the name we're going to show is totally printable.  some
112   // users of entities have odd notions of hostname strings.  there are no
113   // rules requiring these to be readable normal strings.
114   for (int i = 0; i < chewed_host.length(); i++) {
115     if (!parser_bits::is_printable_ascii(chewed_host[i]))
116       chewed_host[i] = REPLACEMENT_CHARACTER;
117   }
118   return a_sprintf("%d.%d.%d.%s", _add_in, _sequencer, _pid, chewed_host.s());
119 }
120
121 astring octopus_entity::mangled_form() const
122 {
123   astring hostdump;
124   byte_array temp_form(_hostname->length() + 1, (abyte *)_hostname->observe());
125   byte_formatter::bytes_to_string(temp_form, hostdump, false);
126   return a_sprintf("%d.%d.%d.%s", _add_in, _sequencer, _pid, hostdump.s());
127 }
128
129 void octopus_entity::breakout(const astring &mangled_form, astring &hostname,
130     int &process_id, int &sequencer, int &add_in)
131 {
132   // there is pretty much no error checking here.
133   astring dupe = mangled_form;  // allows us to destroy the id.
134   sscanf(dupe.s(), "%d", &add_in);
135   dupe.zap(0, dupe.find('.'));
136   sscanf(dupe.s(), "%d", &sequencer);
137   dupe.zap(0, dupe.find('.'));
138   sscanf(dupe.s(), "%d", &process_id);
139   dupe.zap(0, dupe.find('.'));
140   hostname = dupe;
141 }
142
143 bool octopus_entity::operator == (const octopus_entity &that) const
144 {
145   return (_add_in == that._add_in)
146       && (_pid == that._pid)
147       && (_sequencer == that._sequencer)
148       && (*_hostname == *that._hostname);
149 }
150
151 void octopus_entity::pack(byte_array &packed_form) const
152 {
153   _hostname->pack(packed_form);
154   attach(packed_form, _pid);
155   attach(packed_form, _sequencer);
156   attach(packed_form, _add_in);
157 }
158        
159 bool octopus_entity::unpack(byte_array &packed_form)
160 {
161   if (!_hostname->unpack(packed_form)) return false;
162   if (!detach(packed_form, _pid)) return false;
163   if (!detach(packed_form, _sequencer)) return false;
164   if (!detach(packed_form, _add_in)) return false;
165   return true;
166 }
167
168 //////////////
169
170 int octopus_request_id::packed_size() const
171 { return _entity.packed_size() + sizeof(int); }
172
173 astring octopus_request_id::mangled_form() const
174 { return _entity.mangled_form() + a_sprintf("/%d", _request_num); }
175
176 astring octopus_request_id::text_form() const
177 { return _entity.text_form() + a_sprintf("/%d", _request_num); }
178
179 bool octopus_request_id::blank() const
180 { return _entity.blank() || !_request_num; }
181
182 octopus_request_id octopus_request_id::randomized_id()
183 {
184   chaos randona;
185   return octopus_request_id(
186       octopus_entity(string_manipulation::make_random_name(),
187           application_configuration::process_id(), randona.inclusive(0, MAXINT32 / 2),
188           randona.inclusive(0, MAXINT32 / 2)),
189       randona.inclusive(0, MAXINT32 / 2));
190 }
191
192 octopus_request_id octopus_request_id::from_text(const astring &to_convert)
193 {
194   // find the slash, starting at the end.
195   int indy = to_convert.find('/', to_convert.end(), true);
196   if (negative(indy)) return octopus_request_id();  // bad format.
197   astring partial = to_convert.substring(0, indy - 1);
198   int req_id = to_convert.substring(indy + 1, to_convert.end()).convert(0);
199   return octopus_request_id(octopus_entity::from_text(partial), req_id);
200 }
201
202 void octopus_request_id::pack(byte_array &packed_form) const
203 {
204   _entity.pack(packed_form);
205   attach(packed_form, _request_num);
206 }
207
208 bool octopus_request_id::unpack(byte_array &packed_form)
209 {
210   if (!_entity.unpack(packed_form)) return false;
211   if (!detach(packed_form, _request_num)) return false;
212   return true;
213 }
214
215 } // namespace.
216