1 module tagion.monitor.Monitor; 2 3 //import std.bitmanip : BitArray; 4 5 import tagion.hashgraph.Event : Event; 6 import tagion.hashgraph.HashGraph : HashGraph; 7 import tagion.hashgraph.HashGraphBasic : Tides; 8 import tagion.hashgraph.Round; 9 import tagion.hashgraphview.EventMonitorCallbacks : EventMonitorCallbacks; 10 import tagion.network.ListenerSocket; 11 12 //import tagion.hashg : EventMonitorCallbacks; //NetCallbacks; 13 //import tagion.gossip.GossipNet : StdGossipNet; 14 import std.format; 15 import std.string; 16 import tagion.Keywords; 17 import tagion.basic.ConsensusExceptions : ConsensusException; 18 import tagion.basic.Message; 19 import tagion.basic.Types : FileExtension; 20 import tagion.basic.basic : EnumText, basename; 21 import tagion.basic.tagionexceptions : TagionException; 22 import tagion.crypto.Types : Pubkey; 23 import tagion.hibon.Document; 24 import tagion.hibon.HiBON; 25 import tagion.hibon.HiBONJSON; 26 import tagion.logger.Logger; 27 import tagion.utils.BitMask; 28 29 @safe 30 class MonitorException : TagionException { 31 this(immutable(char)[] msg, string file = __FILE__, size_t line = __LINE__) pure { 32 super(msg, file, line); 33 } 34 } 35 36 HiBON bitarray2bool(const(BitMask) bits) @trusted { 37 auto mask = new HiBON; 38 uint i; 39 foreach (n; bits[]) { 40 mask[i++] = n; 41 } 42 return mask; 43 } 44 45 //import core.thread : dur, msecs, seconds; 46 import core.thread; 47 import std.concurrency; 48 import std.socket; 49 import std.stdio : writefln, writeln; 50 51 @safe 52 class MonitorCallBacks : EventMonitorCallbacks { 53 protected enum _params = [ 54 "altitude", 55 "mother", 56 "father", 57 "order", 58 "number", 59 "payload", 60 "famous", 61 "famous_votes", 62 "remove", 63 "list", 64 "epoch", 65 "strong_votes", 66 "decided", 67 "decided_count", 68 "witness", 69 "witness_mask", 70 "received_number", 71 "coin", 72 "coin_round", 73 "round", 74 "is_grounded", 75 "count", 76 ]; 77 mixin(EnumText!("Params", _params)); 78 79 protected { 80 Tid _socket_thread_id; 81 // Tid _network_socket_tread_id; 82 } 83 // immutable uint _global_node_id; 84 immutable FileExtension ext; 85 86 @trusted 87 void socket_send(const(HiBON) hibon) nothrow { 88 89 void inner_send() { 90 const doc = Document(hibon); 91 92 with (FileExtension) { 93 switch (ext) { 94 case json: 95 // log("SENDING JSON: %s", doc.toJSON.toString); 96 _socket_thread_id.send(doc.toJSON.toString); 97 break; 98 case hibon: 99 // log("SENDING HIBON"); 100 _socket_thread_id.send(doc); 101 break; 102 default: 103 throw new MonitorException(message("Bad fileformat %s. Only %s and %s allowed", json, hibon)); 104 } 105 } 106 } 107 108 try { 109 inner_send(); 110 } 111 catch (Exception e) { 112 log.error("Monitor callback failed\n%s", e); 113 } 114 } 115 116 static HiBON createHiBON(const(Event) e) nothrow { 117 auto hibon = new HiBON; 118 119 try { 120 hibon[basename!(e.id)] = e.id; 121 hibon[basename!(e.node_id)] = e.node_id; 122 hibon[Params.count] = Event.count; 123 if (e.mother !is null) { 124 hibon[Params.mother] = e.mother.id; 125 } 126 if (e.father !is null) { 127 hibon[Params.father] = e.father.id; 128 } 129 130 } 131 catch (Exception excp) { 132 // empty 133 } 134 return hibon; 135 } 136 137 const(string) getBitMaskString(const(BitMask) bitmask, uint node_size) @trusted { 138 return format("%*.*s", node_size, node_size, bitmask); 139 } 140 141 nothrow { 142 import tagion.basic.Debug; 143 import tagion.hibon.HiBONJSON; 144 145 void connect(const(Event) e) { 146 147 immutable _witness = e.witness !is null; 148 149 auto hibon = createHiBON(e); 150 151 try { 152 hibon[Params.altitude] = e.altitude; 153 hibon[Params.order] = e.order; 154 if (e.hasRound) { 155 hibon[Params.number] = e.round.number; 156 } 157 if (e.mother !is null) { 158 hibon[Params.mother] = e.mother.id; 159 } 160 if (e.father !is null) { 161 hibon[Params.father] = e.father.id; 162 } 163 if (!e.payload.empty) { 164 hibon[Params.payload] = e.payload; 165 } 166 } 167 catch (Exception excp) { 168 //empty 169 } 170 171 socket_send(hibon); 172 } 173 174 void witness(const(Event) e) { 175 immutable _witness = e.witness !is null; 176 auto hibon = createHiBON(e); 177 try { 178 hibon[Params.witness] = _witness; 179 } 180 catch (Exception excp) { 181 // empty 182 } 183 socket_send(hibon); 184 } 185 186 void round_received(const(Event) e) { 187 auto hibon = createHiBON(e); 188 try { 189 hibon[Params.received_number] = e.round_received.number; 190 } 191 catch (Exception excp) { 192 //empty 193 } 194 195 socket_send(hibon); 196 } 197 198 void round_decided(const(Round.Rounder) rounder) { 199 // auto hibon = new HiBON; 200 // auto round = new HiBON; 201 // const r = rounder.last_decided_round; 202 203 // assumeWontThrow({ 204 // round[Params.number] = r.number; 205 // round[Params.decided] = true; 206 // round[Params.decided_count] = rounder.cached_decided_count; // decided_count; 207 // }); 208 209 // socket_send(hibon); 210 } 211 212 void coin_round(const(Round) r) { 213 // auto hibon = new HiBON; 214 // auto round = new HiBON; 215 // assumeWontThrow({ round[Params.number] = r.number; round[Params.coin] = true; hibon[Params.round] = round; }); 216 217 // socket_send(hibon); 218 } 219 220 void looked_at(const(Event) e) { 221 // auto hibon=createHiBON(e); 222 // auto round=new HiBON; 223 // round[Keywords.number]=e.round.number; 224 // round[Keywords.looked_at_mask]=bitarray2bool(e.round.looked_at_mask); 225 // round[Keywords.looked_at_count]=cast(int)e.round.looked_at_count; 226 // round[Keywords.seeing_completed]=cast(int)e.round.seeing_completed; 227 // round[Keywords.completed]=cast(int)e.round.completed; 228 229 // hibon[Keywords.round]=round; 230 // socket_send(hibon); 231 } 232 233 void famous(const(Event) e) { 234 auto hibon = createHiBON(e); 235 236 try { 237 hibon[Params.famous] = e.isFamous(); 238 } 239 catch (Exception excp) { 240 // empty 241 } 242 socket_send(hibon); 243 } 244 245 void son(const(Event) e) { 246 // auto hibon=createHiBON(e); 247 // hibon[Keywords.son]=e.son.id; 248 // socket_send(hibon); 249 } 250 251 void daughter(const(Event) e) { 252 // auto hibon=createHiBON(e); 253 // hibon[Keywords.daughter]=e.daughter.id; 254 // socket_send(hibon); 255 } 256 257 void round(const(Event) e) { 258 auto hibon = createHiBON(e); 259 auto round = new HiBON; 260 try { 261 round[Params.number] = e.round.number; 262 round[Keywords.completed] = e.round.decided; 263 hibon[Keywords.round] = round; 264 } 265 catch (Exception excp) { 266 //empty 267 } 268 socket_send(hibon); 269 } 270 271 void forked(const(Event) e) { 272 // auto hibon=createHiBON(e); 273 // hibon[Keywords.forked]=e.forked; 274 // socket_send(hibon); 275 } 276 277 void remove(const(Event) e) { 278 // set the daugther to be grounded 279 set_grounded(e.daughter); 280 281 auto hibon = createHiBON(e); 282 try { 283 hibon[Params.remove] = true; 284 } 285 catch (Exception excp) { 286 // empty 287 } 288 // assumeWontThrow({ hibon[Params.remove] = true; }); 289 socket_send(hibon); 290 } 291 292 // sets the event to grounded 293 void set_grounded(const(Event) e) { 294 // log("SETTING GROUNDED"); 295 // auto hibon = createHiBON(e); 296 // try { 297 // hibon[Params.is_grounded] = true; 298 // } catch (Exception excp) { 299 // // empty 300 // } 301 // socket_send(hibon); 302 } 303 304 void remove(const(Round) r) { 305 // auto hibon = new HiBON; 306 // auto round = new HiBON; 307 // assumeWontThrow({ round[Params.number] = r.number; round[Params.remove] = true; }); 308 // // hibon[Keywords.round]=round; 309 // socket_send(hibon); 310 } 311 312 void strong_vote(const(Event) e, immutable uint votes) { 313 // auto hibon = createHiBON(e); 314 // assumeWontThrow({ hibon[Params.strong_votes] = votes; }); 315 // socket_send(hibon); 316 } 317 318 void iterations(const(Event) e, const uint count) { 319 // auto hibon=createHiBON(e); 320 // hibon[Keywords.iterations]=count; 321 // socket_send(hibon); 322 } 323 324 void epoch(const(Event[]) received_events) { 325 // auto epoch = new HiBON; 326 // auto hibon = new HiBON; 327 // auto list = new HiBON[received_events.length]; 328 // assumeWontThrow({ 329 // foreach (i, e; received_events) { 330 // auto hibon_e = new HiBON; 331 // hibon_e[basename!(e.id)] = e.id; 332 // list[i] = hibon_e; 333 // } 334 // hibon[Params.list] = list; 335 // epoch[Params.epoch] = hibon; 336 // }); 337 // socket_send(epoch); 338 } 339 340 void receive(lazy const(Document) doc) { 341 342 } 343 344 void consensus_failure(const(ConsensusException) e) { 345 // writefln("Impl. needed. %s msg=%s ", __FUNCTION__, e.msg); 346 } 347 348 // void wavefront_state_receive(const(Document) doc) { 349 // //import tagion.Base : cutHex; 350 // // writefln("Impl. needed. %s node=%s ", __FUNCTION__, n.pubkey.cutHex); 351 // } 352 353 void sent_tidewave(immutable(Pubkey) receiving_channel, const(Tides) tides) { 354 // writefln("Impl. needed. %s tides=%d ", __FUNCTION__, tides.length); 355 } 356 357 void received_tidewave(immutable(Pubkey) sending_channel, const(Tides) tides) { 358 // writefln("Impl. needed. %s tides=%d ", __FUNCTION__, tides.length); 359 } 360 361 void receive(const(Document) doc) { 362 // writefln("Impl. needed. %s ", __FUNCTION__); 363 } 364 365 void send(const(Pubkey) channel, lazy const(Document) doc) { 366 //import tagion.Base : cutHex; 367 // writefln("Impl. needed. %s channel=%s", __FUNCTION__, channel.cutHex); 368 } 369 370 void exiting(const(Pubkey) owner_key, const(HashGraph)) { 371 //import tagion.Base : cutHex; 372 // writefln("Impl. needed. %s node=%s ", __FUNCTION__, n.pubkey.cutHex); 373 } 374 } 375 376 @trusted 377 this(Tid socket_thread_id, 378 const FileExtension dataformat) { 379 this._socket_thread_id = socket_thread_id; 380 this.ext = dataformat; 381 } 382 383 @trusted 384 void sendMessage(string msg) { 385 _socket_thread_id.send(msg); 386 } 387 388 }