Skip to content

Commit e3de4b9

Browse files
committed
- cache hydrated objects per-remote peer in the ObjectDiscoveryAgent
- prevent re-hashing stuff in other places
1 parent 9a5d823 commit e3de4b9

File tree

6 files changed

+87
-40
lines changed

6 files changed

+87
-40
lines changed

src/data/model/hashing/Hashing.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,21 @@ class Hashing {
1515
seed = '';
1616
}
1717

18-
let firstPass = Hashing.sha.sha256base64('0a' + text + seed);
19-
let secondPass = Hashing.rmd.rmd160base64(text + firstPass);
18+
//const t = Date.now();
19+
20+
const firstPass = Hashing.sha.sha256base64('0a' + text + seed);
21+
const secondPass = Hashing.rmd.rmd160base64(text + firstPass);
22+
23+
//console.trace();
24+
//console.log(' *** hashing took ', Date.now() - t, ' for result ', secondPass);
2025

2126
return secondPass;
2227
}
2328

2429
static forValue(value: any, seed?: string) : Hash{
25-
let text = Serialization.default(value);
30+
//const t = Date.now()
31+
const text = Serialization.default(value);
32+
//console.log(' *** serialization took ', Date.now() - t);
2633

2734
return Hashing.forString(text, seed);
2835
}

src/data/model/immutable/HashedObject.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ abstract class HashedObject {
205205

206206
hash(seed?: string): Hash {
207207

208+
//console.log('about to hash a ' + this.getClassName())
209+
//console.trace();
210+
208211
let hash = this.customHash(seed);
209212

210213
if (hash === undefined) {

src/mesh/agents/discovery/ObjectDiscoveryAgent.ts

Lines changed: 68 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Endpoint, LinkupMessage, NetworkAgent, NetworkEventType } from '../netw
77
import { ObjectBroadcastAgent, ObjectBroadcastRequest, ObjectBroadcastReply } from './ObjectBroadcastAgent';
88

99
import { AsyncStream, BufferedAsyncStream, BufferingAsyncStreamSource, AsyncStreamSource, FilteredAsyncStreamSource } from 'util/streams';
10+
import { LRUCache } from 'util/caching';
1011

1112
type Params = {
1213
broadcastedSuffixBits : number,
@@ -28,6 +29,10 @@ class ObjectDiscoveryAgent implements Agent {
2829

2930
static newestReplyFirst = (a: ObjectDiscoveryReply, b: ObjectDiscoveryReply) => (b.timestamp - a.timestamp);
3031

32+
private static makeEndpointObjectPair(hash: Hash, source: Endpoint, destination: Endpoint) {
33+
return hash + '_' + source.replaceAll('_', '__') + '_' + destination.replaceAll('_', '__');
34+
}
35+
3136
pod?: AgentPod;
3237

3338

@@ -39,6 +44,7 @@ class ObjectDiscoveryAgent implements Agent {
3944

4045
streamSource: BufferingAsyncStreamSource<ObjectDiscoveryReply>;
4146

47+
discoveredEndpointObjectPairs: LRUCache<string, HashedObject>;
4248

4349
wasShutdown = false;
4450

@@ -60,6 +66,8 @@ class ObjectDiscoveryAgent implements Agent {
6066
this.lastQueryingTimePerServer = new Map();
6167

6268
this.streamSource = new BufferingAsyncStreamSource(this.params.maxStoredReplies);
69+
70+
this.discoveredEndpointObjectPairs = new LRUCache(256);
6371
}
6472

6573
getAgentId(): string {
@@ -169,52 +177,81 @@ class ObjectDiscoveryAgent implements Agent {
169177

170178
if (msg.agentId === this.getAgentId()) {
171179

172-
const reply = msg.content as ObjectBroadcastReply;
173-
174180

175181

176-
let replyHash: Hash|undefined = undefined;
177-
let object: HashedObject | undefined = undefined;
178-
let error: string | undefined = undefined;
179-
try {
180-
object = HashedObject.fromLiteralContext(reply.literalContext);
181-
replyHash = object.hash();
182-
} catch (e: any) {
182+
this.processReply(msg);
183+
184+
}
183185

184-
// Since anybody may reply with _anything_, only replies that at least match the hash
185-
// suffix being queried will be reported back to the caller.
186+
}
187+
}
186188

187-
ObjectDiscoveryAgent.log.warning('Error deliteralizing object discovery reply:' + e);
188-
object = undefined;
189-
replyHash = undefined;
190-
const literal = reply.literalContext.literals[reply.literalContext.rootHashes[0]];
189+
private processReply(msg: LinkupMessage) {
191190

192-
if (literal !== undefined && LiteralUtils.validateHash(literal)) {
193-
if (literal.hash === reply.literalContext.rootHashes[0]) {
194-
replyHash = literal.hash;
195-
}
196-
}
191+
const reply = msg.content as ObjectBroadcastReply;
197192

198-
error = String(e);
199-
}
193+
let replyHash: Hash|undefined = undefined;
194+
let object: HashedObject | undefined = undefined;
195+
let error: string | undefined = undefined;
200196

201-
if (replyHash === reply.literalContext.rootHashes[0] &&
202-
this.hexHashSuffix === Hashing.toHex(replyHash).slice(-this.hexHashSuffix.length) &&
203-
this.localEndpoints.has(msg.destination)) {
197+
204198

205-
ObjectDiscoveryAgent.log.trace(() => 'Received object with hash ' + replyHash + ' from ' + msg.source + ' at ' + msg.destination);
199+
try {
200+
const declaredHash = reply.literalContext.rootHashes.length === 1?
201+
reply.literalContext.rootHashes[0]
202+
:
203+
'';
206204

207-
let item = {source: msg.source, destination: msg.destination, hash: replyHash, object: object, error: error, timestamp: Date.now()};
208-
205+
if (this.hexHashSuffix === Hashing.toHex(declaredHash).slice(-this.hexHashSuffix.length)) {
206+
207+
const cacheKey = ObjectDiscoveryAgent.makeEndpointObjectPair(declaredHash, msg.source, msg.destination);
208+
object = this.discoveredEndpointObjectPairs.get(cacheKey);
209209

210-
this.streamSource.ingest(item);
211-
210+
if (object === undefined) {
211+
object = HashedObject.fromLiteralContext(reply.literalContext);
212+
replyHash = object.hash();
213+
214+
if (replyHash === declaredHash) {
215+
this.discoveredEndpointObjectPairs.set(cacheKey, object);
216+
}
212217
} else {
213-
ObjectDiscoveryAgent.log.debug('Error validating object discovery reply');
218+
replyHash = declaredHash;
214219
}
220+
}
221+
222+
223+
} catch (e: any) {
224+
225+
// Since anybody may reply with _anything_, only replies that at least match the hash
226+
// suffix being queried will be reported back to the caller.
227+
228+
ObjectDiscoveryAgent.log.warning('Error deliteralizing object discovery reply:' + e);
229+
object = undefined;
230+
replyHash = undefined;
231+
const literal = reply.literalContext.literals[reply.literalContext.rootHashes[0]];
215232

233+
if (literal !== undefined && LiteralUtils.validateHash(literal)) {
234+
if (literal.hash === reply.literalContext.rootHashes[0]) {
235+
replyHash = literal.hash;
236+
}
216237
}
217238

239+
error = String(e);
240+
}
241+
242+
if (replyHash === reply.literalContext.rootHashes[0] &&
243+
this.hexHashSuffix === Hashing.toHex(replyHash).slice(-this.hexHashSuffix.length) &&
244+
this.localEndpoints.has(msg.destination)) {
245+
246+
ObjectDiscoveryAgent.log.trace(() => 'Received object with hash ' + replyHash + ' from ' + msg.source + ' at ' + msg.destination);
247+
248+
let item = {source: msg.source, destination: msg.destination, hash: replyHash, object: object, error: error, timestamp: Date.now()};
249+
250+
251+
this.streamSource.ingest(item);
252+
253+
} else {
254+
ObjectDiscoveryAgent.log.debug('Error validating object discovery reply');
218255
}
219256
}
220257

src/mesh/agents/network/SecureNetworkAgent.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,9 @@ class SecureNetworkAgent implements Agent {
406406

407407
secureForReceiving(connId: ConnectionId, localIdentity: Identity, timeout=DEFAULT_TIMEOUT) {
408408

409-
SecureNetworkAgent.logger.trace('Asked to verify ' + connId + ' for receiving with ' + localIdentity.hash());
409+
SecureNetworkAgent.logger.trace('Asked to verify ' + connId + ' for receiving with ' + localIdentity.getLastHash());
410410

411-
const identityHash = localIdentity.hash();
411+
const identityHash = localIdentity.getLastHash();
412412

413413
let secured = this.getOrCreateConnectionSecuredForReceiving(connId, identityHash);
414414
secured.identity = localIdentity;
@@ -799,7 +799,7 @@ class SecureNetworkAgent implements Agent {
799799
private sendIdentity(connId: ConnectionId, identity: Identity, identityHash?: Hash) {
800800

801801
if (identityHash === undefined) {
802-
identityHash = identity.hash();
802+
identityHash = identity.getLastHash();
803803
}
804804

805805
let content: SendIdentityMessage = {

src/storage/store/Store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ class Store {
515515
}*/
516516
}
517517

518-
//console.log('+++ loaded ' + hash, object?.getClassName(), new Error().stack);
518+
//console.log('+++ loaded ' + hash, object?.getClassName());
519519

520520
if (object instanceof MutationOp) {
521521
//console.log('+++ target: ' + object.getTargetObject().getLastHash() + ' (' + object.getTargetObject().getClassName() + ')');

src/util/events.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { Logger, LogLevel } from 'util/logging';
1515

1616

1717
type hash = string;
18-
type hashable = { hash(): hash; };
18+
type hashable = { getLastHash(): hash; };
1919

2020
type location<T> = {name: string, emitter: T};
2121
//type path<T> = Array<location<T>>;
@@ -46,7 +46,7 @@ class EventRelay<T extends hashable> {
4646
constructor(source: T, upstreamRelays: Map<string, EventRelay<T>>) {
4747

4848
this.emitter = source;
49-
this.emitterHash = source.hash();
49+
this.emitterHash = source.getLastHash();
5050

5151
this.upstreamRelays = new Map();
5252

0 commit comments

Comments
 (0)