Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

351
LINES

< > BotCompany Repo | #1024472 // agi.blue Core Include

JavaX fragment (include) [tags: use-pretranspiled]

1  
sbool maintainPositionalIndex = true;
2  
3  
// in main DB
4  
concept Slice {
5  
  GlobalID globalID = aGlobalIDObject();
6  
  S caseID;
7  
  S name;
8  
  bool indexed = true;
9  
  long sliceDumped; // wall time, set before dump starts
10  
11  
  new Ref<User> owner;
12  
13  
  S defaultCaseID() {
14  
    ret uniqueFileNameUsingMD5_80_v2(name + " " + globalID);
15  
  }
16  
17  
  GlobalID globalID() { ret globalID; }
18  
}
19  
20  
// in any DB
21  
concept Page {
22  
  !include #1024467 // compact global ID
23  
  short flags;
24  
  
25  
  //S globalID = aGlobalID();
26  
  S q;
27  
28  
  void _onLoad() {
29  
    S id = cget(this, 'globalID);
30  
    if (id != null) {
31  
      setGlobalID(id);
32  
      cset(this, globalID := null);
33  
    }
34  
  }
35  
36  
  // for in-VM helper bots
37  
  void quickPost(S key, S value) {
38  
    agiBlue().new GetEntriesAndPost(_concepts).go(this, litmap(+key, +value));
39  
  }
40  
  
41  
  AGIBlue agiBlue() { ret (AGIBlue) mapGet(_concepts.miscMap, 'agiBlue); }
42  
  AGIBlue.LoadedSlice loadedSlice() { ret (AGIBlue.LoadedSlice) mapGet(_concepts.miscMap, 'loadedSlice); }
43  
}
44  
45  
abstract concept AbstractEntry {
46  
  new Ref<Page> page;
47  
  int count;
48  
  S key;
49  
  S ip;
50  
  new Ref<Signer> signer;
51  
  
52  
  S q() { Page p = page!; ret p == null ? null : page->q; }
53  
}
54  
55  
concept Entry > AbstractEntry {
56  
  S globalID = aGlobalID(); // TODO: migrate to object
57  
  S value;
58  
}
59  
60  
/*concept MultiLineEntry > AbstractEntry {
61  
  GlobalID globalID = aGlobalIDObject();
62  
  S value;
63  
}*/
64  
65  
concept BlobEntry > AbstractEntry {
66  
  GlobalID globalID = aGlobalIDObject();
67  
  long length;
68  
  S md5;
69  
  S contentType;
70  
  
71  
  GlobalID globalID() { ret globalID; }
72  
}
73  
74  
// in main DB?
75  
concept Signer {
76  
  S globalID = aGlobalID();
77  
  S publicKey;
78  
  bool trusted;
79  
  S approvedBy;
80  
}
81  
82  
concept User {
83  
  GlobalID globalID = aGlobalIDObject();
84  
  long lastSeen;
85  
}
86  
87  
concept CookieUser > User {
88  
  S cookie;
89  
90  
  toString { ret "[cookieUser]"; }
91  
}
92  
93  
concept GoogleUser > User {
94  
  long googleLogInDate;
95  
  S googleEmail, googleFirstName, googleLastName;
96  
  bool googleEmailVerified;
97  
98  
  toString { ret googleFirstName + " " + googleLastName; }
99  
}
100  
101  
concept MinimalUser > User {
102  
  S userName, encryptedPassword; // TODO
103  
104  
  toString { ret "[minimalUser] " + userName; }
105  
}
106  
107  
// supply password with _pass
108  
concept JustPasswordUser > User {
109  
  S password;
110  
}
111  
112  
// in main DB
113  
concept Session {
114  
  S cookie;
115  
  S selectedSlice; // global ID
116  
  Page slicePage; // phasing out
117  
  new Ref<User> user;
118  
}
119  
120  
// singleton concept in every DB
121  
concept SliceInfo {
122  
  GlobalID globalID;
123  
  LS mandatoryBotVMBusIDs;
124  
  bool openPosting = true; // allow posting by anyone
125  
}
126  
127  
sclass CentralIndexEntry {
128  
  Set<Slice> slices = synchroLinkedHashSet();
129  
}
130  
131  
abstract sclass AGIBlue {
132  
  // Customizations:
133  
  
134  
  bool asyncSearch = false;
135  
  bool allowMultipleCasesInValues = true;
136  
  bool showSliceSelector = true;
137  
  bool showGoogleLogIn = true;
138  
  bool makeAllKeysPages = true;
139  
  bool makeAllValuesPages = true; 
140  
  bool legacy = true; // We still have slices without applied fixes
141  
  bool dumpSlicesOnAnyChange = true; // testing
142  
  
143  
  int maxSliceNameLength = 1024;
144  
  int displayLength = 140;
145  
  int sideDisplayLength = 50; // when in side bar
146  
  int searchResultsToShow = 50;
147  
  S sideSearchType = 'literal;
148  
  int maxBackgroundSlices = 1000;
149  
  
150  
  // end of customizations
151  
  
152  
  long cloningSince, clonedSince;
153  
  bool isClone;
154  
  
155  
  // general methods
156  
157  
  File sliceDumpFile(Slice slice) {
158  
    ret programFile("slice-dumps/" + or2(slice.caseID, "main") + ".slice");
159  
  }
160  
  
161  
  File dumpSliceToFile(LoadedSlice slice) {
162  
    ret withDBLock(slice.cc, func -> File {
163  
      cset(slice.sliceConcept, sliceDumped := now());
164  
      File file = sliceDumpFile(slice.sliceConcept);
165  
      new LS lines;
166  
      for (Page p : list(slice.cc, Page))
167  
        lines.add(quote(p.q));
168  
      for (Entry e : list(slice.cc, Entry))
169  
        lines.add(sfu(tripleToList(entryToTriple(e))));
170  
      saveLinesAsTextFile(file, lines);
171  
      ret file;
172  
    });
173  
  }
174  
  
175  
  Page pageFromQ(Concepts cc, S q) {
176  
    ret empty(q) ? null : uniqCI_sync(cc, Page, +q);
177  
  }
178  
  
179  
    // executed by rst_index
180  
  void makeCentralIndex() {
181  
    newCentralIndex.clear();
182  
    long time = now();
183  
    pcall {
184  
      for (Slice slice : conceptsWhere(Slice, indexed := true))
185  
        addToNewCentralIndex(slice);
186  
    }
187  
    centralIndex.putAll(newCentralIndex);
188  
    removeAllKeysNotIn(centralIndex, newCentralIndex);
189  
    newCentralIndex.clear();
190  
    centralIndexMade = now();
191  
    centralIndexMadeIn = now()-time;
192  
  }
193  
  
194  
  void addToNewCentralIndex(Slice slice) {
195  
    for (S s : sliceDump_pageNamesIncludingKeys(sliceDumpFile(slice)))
196  
      newCentralIndexGet(s).slices.add(slice);
197  
  }
198  
199  
  CentralIndexEntry centralIndexGet(S s) { ret getOrCreate CentralIndexEntry(centralIndex, s); }
200  
  
201  
  CentralIndexEntry newCentralIndexGet(S s) { ret getOrCreate CentralIndexEntry(newCentralIndex, s); }
202  
  
203  
  Cl<Slice> centralIndexGetSlices(S s) {
204  
    CentralIndexEntry e = centralIndexGet(s);
205  
    ret e == null ? null : e.slices;
206  
  }
207  
  
208  
  void dbLog(O... params) {
209  
    logStructure(programFile("db.log"), ll(params));
210  
  }
211  
  
212  
  class LoadedSlice { // non-persistent class
213  
    S caseID;
214  
    Concepts cc;
215  
    Slice sliceConcept;
216  
    SliceInfo sliceInfo;
217  
    long lastAccess = sysNow();
218  
    ReliableSingleThread rstDumpSlice = new(r {
219  
      dumpSliceToFile(LoadedSlice.this);
220  
      rst_index.trigger(); // rebuild index too - TODO: only this slice
221  
    });
222  
    bool haltSliceDumping;
223  
224  
    // indices
225  
    
226  
    ConceptFieldIndexDesc idx_latestEntries, idx_latestCreatedPages, idx_latestChangedPages;
227  
228  
    ReliableSingleThread rstMakePositionalIndex = new(r makePositionalIndex_impl);
229  
    PositionalTokenIndex2 positionalIndex;
230  
    
231  
    void makePositionalIndex_impl {
232  
      time "Making positional index" {
233  
        positionalIndex = positionalTokenIndex2_wordTok(collect q(list(cc, Page)));
234  
      }
235  
    }
236  
    
237  
    *(S *caseID, Concepts *cc) {
238  
      csetAll(list(cc, Page), slice := null, url := null); // clear legacy fields
239  
      releaseEmptyFieldValuesOfAllConcepts(cc);
240  
      indexThings();
241  
      
242  
      // forward changes to Slice concept
243  
      onConceptsChange(cc, rOnceAtATimeOnly(r {
244  
        cset(sliceConcept, _modified := now())
245  
  ;
246  
        if (!haltSliceDumping && dumpSlicesOnAnyChange && nempty(caseID)) {
247  
          rstDumpSlice.trigger();
248  
        }
249  
        if (maintainPositionalIndex) rstMakePositionalIndex.trigger();
250  
      }));
251  
      
252  
      if (makeAllKeysPages && legacy)
253  
        for (Entry e : list(cc, Entry))
254  
          pageFromQ(e.key);
255  
          
256  
      if (makeAllValuesPages && legacy)
257  
        for (Entry e : list(cc, Entry))
258  
          pageFromQ(e.value);
259  
    }
260  
    
261  
    void initialSetup(GlobalID globalID) {
262  
      sliceInfo = uniq(cc, SliceInfo);
263  
      cset(sliceInfo, +globalID);
264  
    }
265  
    
266  
    SliceInfo sliceInfo() { ret sliceInfo; }
267  
    
268  
    // create if not there
269  
    Page pageFromQ(S q) {
270  
      ret AGIBlue.this.pageFromQ(cc, q);
271  
    }
272  
  
273  
    void indexThings() {
274  
      indexConceptFieldsCI(cc, Page, 'q, Entry, 'key, Entry, 'value);
275  
      indexConceptFields(cc, Signer, 'publicKey);
276  
      indexConceptFields(cc, Session, 'cookie);
277  
      indexSingletonConcept(cc, SliceInfo);
278  
      idx_latestCreatedPages = new ConceptFieldIndexDesc(cc, Page, 'created);
279  
      idx_latestChangedPages = new ConceptFieldIndexDesc(cc, Page, '_modified);
280  
      idx_latestEntries = new ConceptFieldIndexDesc(cc, Entry, 'created);
281  
      
282  
      if (maintainPositionalIndex) rstMakePositionalIndex.trigger();
283  
    }
284  
    
285  
    bool isMainSlice() { ret empty(caseID); }
286  
    GlobalID globalID() { ret sliceConcept.globalID; }
287  
    S name() { ret sliceConcept.name; }
288  
  }
289  
  
290  
  // global vars
291  
  
292  
  ConceptsLoadedOnDemand fan;
293  
  ConceptsLoadedOnDemand backgroundFan;
294  
  Map<S, LoadedSlice> loadedSlices = syncMap();
295  
  Map<S, LoadedSlice> backgroundSlices = syncMap();
296  
  Map<S, CentralIndexEntry> centralIndex = ciMap();
297  
  Map<S, CentralIndexEntry> newCentralIndex = ciMap();
298  
  long centralIndexMade; // wall time
299  
  long centralIndexMadeIn;
300  
  ReliableSingleThread rst_index = new(r makeCentralIndex);
301  
  ConceptFieldIndexDesc idx_slicesByModification, idx_usersBySeen;
302  
  ConceptFieldIndexCI idx_slicesByName, idx_usersByName;
303  
  
304  
  class GetEntriesAndPost {
305  
    Concepts cc;
306  
    L<Entry> entries;
307  
    Entry entry;
308  
    bool newEntry;
309  
    Signer signer;
310  
    Session session;
311  
    
312  
    *(Concepts *cc, Session *session) {} // migrate to this constructor
313  
    *(Concepts *cc) {}
314  
    
315  
    GetEntriesAndPost go(Page page, SS params) {
316  
      S key = trim(params.get('key)), value = trim(params.get('value));
317  
      print("GetEntriesAndPost: " + quote(page.q) + ", " + quote(key) + " := " + quote(value));
318  
      withDBLock {
319  
        entries = findBackRefs(page, Entry);
320  
        if (nempty(key) && nempty(value)) {
321  
          Slice slice = page.loadedSlice().sliceConcept;
322  
          SliceInfo sliceInfo = page.loadedSlice().sliceInfo(); 
323  
          if (!sliceInfo.openPosting && session != null && session.user! != slice.owner!)
324  
            fail("Not owner of slice");
325  
          S ip = subBot_clientIP();
326  
          entry = firstThat(e -> eqic(e.key, key) && eq_icIf(!allowMultipleCasesInValues, e.value, value) && eq(e.ip, ip), entries);
327  
          if (entry == null) {
328  
            print("SAVING");
329  
            Entry e = cnew(cc, Entry, +page, +key, +value, +ip, count := l(entries) + 1, +signer);
330  
            if (makeAllKeysPages) pageFromQ(cc, key);
331  
            if (makeAllValuesPages) pageFromQ(cc, value);
332  
            page.change(); // bump modification date
333  
            entry = e;
334  
            newEntry = true;
335  
            entries.add(entry);
336  
            dbLog("New entry", page := page.q, globalID := e.globalID, count := e.count, +key, +value);
337  
          }
338  
        }
339  
      }
340  
  
341  
      sortByFieldInPlace created(entries);
342  
      numberEntriesInConceptField count(entries);
343  
      this;
344  
    }
345  
  }
346  
347  
  T3S entryToTriple(Entry e) {
348  
    ret e == null ? null : t3(e.page->q, e.key, e.value);
349  
  }
350  
  
351  
} // end of AGIBlue

download  show line numbers  debug dex  old transpilations   

Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1024472
Snippet name: agi.blue Core Include
Eternal ID of this version: #1024472/33
Text MD5: 4526f1cc5755ea87f92ab26037937966
Author: stefan
Category: javax / agi.blue
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-10-14 13:55:16
Source code size: 10131 bytes / 351 lines
Pitched / IR pitched: No / No
Views / Downloads: 265 / 690
Version history: 32 change(s)
Referenced in: [show references]