public IEnumerator Load <R>(DataLoader.IResultReceiver loader, string path) where R : Google.Protobuf.IMessage <R> { //TODO: update csv if necessary (with assetbundle or something) CSVSource s; try { #if UNITY_ANDROID && !UNITY_EDITOR WWW www = new WWW(path); yield return(www); if (!string.IsNullOrEmpty(www.error)) { throw new System.Exception(www.error); } s = new CSVSource(new StringReader(www.text)); #else s = new CSVSource(new StreamReader(TrimBOM(path))); #endif } catch (System.Exception e) { loader.Error = e; yield break; } s.Read(); s.ReadHeader(); Source = s; yield break; }
public IEnumerator Load <R>(DataLoader.IResultReceiver loader, string path) where R : Google.Protobuf.IMessage <R> { //get message parser by reflection PropertyInfo propertyInfo; propertyInfo = typeof(R).GetProperty("Parser", BindingFlags.Public | BindingFlags.Static); // Use the PropertyInfo to retrieve the value from the type by not passing in an instance Google.Protobuf.MessageParser <R> parser = (Google.Protobuf.MessageParser <R>)propertyInfo.GetValue(null, null); //get record name by reflection var eth = Game.Main.RPCMgr.Eth; string contract = path; string name = typeof(R).Name; //load local objects int current_gen = 0; var storage = Game.Main.StorageMgr; var local_records = storage.LoadAllRecords(name, parser, out current_gen); if (current_gen < 0) { loader.Error = new System.Exception("fail to load record"); yield break; } //get size of updated records if (eth[contract] == null) { loader.Error = new System.Exception("contract not exists: name = " + contract); yield break; } var call = eth[contract].Call("recordIdDiff"); Debug.Log("curent_gen:" + current_gen); yield return(call.Exec(name, current_gen)); if (call.Error != null) { loader.Error = call.Error; yield break; } int next_gen; List <List <byte[]> > ids; try { var dto = call.AsDTO <RecordIdDiffOutput>(); if (int.TryParse(dto.NextGen.ToString(), out next_gen) && next_gen > 0) { ids = dto.IdChunks; } else { throw new System.Exception(name + ":gen number is too big or out of range:" + dto.NextGen.ToString()); } } catch (System.Exception e) { Debug.Log("recordIdDiff error:" + e.Message + " at " + e.StackTrace); loader.Error = e; yield break; } //if updated records found, retrieve it from contract if (ids.Count > 0) { HashSet <byte[]> hs = new HashSet <byte[]>(); //de-dupe duplicate record (update multiple time since last updated time) for (int i = 0; i < ids.Count; i++) { for (int j = 0; j < ids[i].Count; j++) { hs.Add(ids[i][j]); } } byte[][] updated_ids_distinct = hs.ToArray(); R[] updated_records = new R[updated_ids_distinct.Length]; //then query updated records for (int n_query = 0; n_query < updated_ids_distinct.Length; n_query += BATCH_QUERY_SIZE) { var batch_ids = updated_ids_distinct.Skip(n_query).Take(BATCH_QUERY_SIZE).ToArray(); Debug.Log(name + ": n_query = " + n_query + " and " + batch_ids.Length); call = eth[contract].Call("getRecords"); yield return(call.Exec(name, batch_ids)); if (call.Error != null) { loader.Error = call.Error; yield break; } try { var rs = call.AsMsgs <R>(parser, 0); for (int i = n_query; i < (n_query + batch_ids.Length); i++) { local_records[batch_ids[i - n_query]] = rs[i]; updated_records[i] = rs[i]; } } catch (System.Exception e) { loader.Error = e; yield break; } } //save updated records into local storage var err = storage.SaveRecords(next_gen, name, updated_ids_distinct, updated_records); if (err != null) { loader.Error = err; yield break; } } else { Debug.Log(name + ": no update since last access:" + local_records.Count); } //set source var s = new ConstractSource <R>(local_records.Count); Source = s; foreach (var kv in local_records) { s.Add(kv.Value); } s.Rewind(); yield break; }