diff --git a/sources/HYCOM.cpp b/sources/HYCOM.cpp new file mode 100644 index 0000000..0fb42d2 --- /dev/null +++ b/sources/HYCOM.cpp @@ -0,0 +1,117 @@ +#define MICHLIB_NOSOURCE +#include "HYCOM.h" +#include "CF.h" +#include +#include + +using michlib::GPL; + +RetVal HYCOMData::GetAdapter(const CLArgs& args, michlib_internal::ParameterListEx& pars) const +{ + static const MString pref = "HYCOMData::GetAdapter"; + + //const bool debug = args.contains("debug"); + + Adapter out(Adapter::ZarrMethod::MNC); + + GPL.UsePrefix("HYCOM"); + + // Get link for dataset + const MString dataset = args.contains("dataset") ? args.at("dataset") : "Forecast"; + + pars.AddParameter("dataset", dataset); + + std::vector urls; + size_t cachettl = GPL.ParameterUValue(dataset + "_CacheTTL", 3600 * 24 * 7); + { + const auto url = GPL.ParameterSValue(dataset + "_URL", ""); + if(url.Exist()) + urls.push_back(url); + else + { + size_t i = 1; + while(true) + { + const auto url = GPL.ParameterSValue(dataset + "_URL" + i, ""); + if(!url.Exist()) break; + urls.push_back(url); + i++; + } + } + } + if(urls.size() == 0) return {pref, "No urls find for datest " + dataset}; + + out.SetTitle(GPL.ParameterSValue(dataset + "_Title", "Unknown")); + pars.AddParameter("title", out.Title()); + + // Open data + std::unique_ptr pnc; + std::vector times; + { + std::vector table; + for(const auto& url: urls) + { + Adapter::TimeRow row; + std::vector ltimes; + + row.beg = table.size() == 0 ? 0 : (table.back().end + 1); + row.file = url; + auto [val, res] = cache->Get(url); + if(!res) + { + pnc.reset(new NCZarr); + auto ret = pnc->OpenMultiNC(url.Split(";")); + if(!ret) return ret.Add(pref, "Can't open link " + url); + auto tvar = CF::GetTVarName(*pnc); + if(!tvar.Exist()) return {pref, "Can't find time variable in the dataset " + dataset}; + if(pnc->NDim(tvar) != 1) return {pref, "Unsupported number of time dimensions: " + MString(pnc->NDim(tvar))}; + + auto timesret = CF::ReadTimes(*pnc, tvar); + if(!timesret) return ret.Add(pref, "Can't read time values from the dataset " + dataset); + ltimes = timesret.Value(); + if(ltimes.size() == 0) return {pref, "No time moments in " + url}; + + michlib::Serializer s; + s.Serialize(ltimes.size()); + for(size_t i = 0; i < ltimes.size(); i++) s.Serialize(ltimes[i]); + val = MString(s.Buf(), s.Len()); + cache->Put(url, val, cachettl); + } + else + { + michlib::Deserializer ds(val.Buf(), val.Len()); + size_t vsize; + bool ok; + ok = ds.Deserialize(vsize); + if(!ok) return {pref, "Cache line for url " + url + " is bad"}; + ltimes.resize(vsize); + for(size_t i = 0; i < vsize; i++) ok = ok && ds.Deserialize(ltimes[i]); + if(!ok) return {pref, "Cache line for url " + url + " is bad"}; + } + row.end = row.beg + ltimes.size() - 1; + times.insert(times.end(), ltimes.begin(), ltimes.end()); + table.push_back(row); + } + out.SetTimeTable(std::move(table)); + } + + if(!pnc) + { + pnc.reset(new NCZarr); + auto ret = pnc->OpenMultiNC(urls[0].Split(";")); + if(!ret) return ret.Add(pref, "Can't open link " + urls[0]); + } + + // Set times + { + auto ret = out.SetTimes(std::move(times), args, pars); + if(!ret) return ret.Add(pref, "Can't filter time values from the dataset " + dataset); + } + + { + auto ret = CF::FillAdapterFromCF(args, pars, out, std::move(pnc)); + if(!ret) return ret.Add(pref, "Can't get adapter"); + } + + return out; +} diff --git a/sources/HYCOM.h b/sources/HYCOM.h index 45453f2..80e9762 100644 --- a/sources/HYCOM.h +++ b/sources/HYCOM.h @@ -14,10 +14,23 @@ class HYCOMData: public LayeredData Type type = TYPE_UNKNOWN; + std::unique_ptr cache; + public: static constexpr const char* name = "HYCOM"; - HYCOMData() = default; + HYCOMData() + { + auto oldprefix = michlib::GPL.UsePrefix("HYCOM"); + // Cache + cache.reset(CreateCache(michlib::GPL.ParameterSValue("Cache", ""))); + if(!cache) + { + michlib::errmessage("Can't init cache"); + cache.reset(new FakeCache); + } + michlib::GPL.UsePrefix(oldprefix); + } MString DataTitle() const { @@ -51,4 +64,7 @@ class HYCOMData: public LayeredData SetTitle(DataTitle()); return LayeredData::Open(dataset); } + + // Adapter + RetVal GetAdapter(const CLArgs& args, michlib_internal::ParameterListEx& pars) const; };