You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnosygnu_xowa/400_xowa/src/gplx/xowa/wikis/data/Xow_db_mgr.java

253 lines
11 KiB

/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.xowa.wikis.data;
import gplx.Byte_;
import gplx.DateAdp;
import gplx.Err_;
import gplx.Guid_adp_;
import gplx.Int_;
import gplx.Int_ary_;
import gplx.Io_mgr;
import gplx.Io_url;
import gplx.List_adp;
import gplx.List_adp_;
import gplx.Ordered_hash;
import gplx.Ordered_hash_;
import gplx.String_;
import gplx.dbs.Db_cmd_mode;
import gplx.dbs.Db_conn;
import gplx.dbs.Db_conn_bldr;
import gplx.dbs.cfgs.Db_cfg_tbl;
import gplx.xowa.Xoa_app_;
import gplx.xowa.Xow_wiki;
import gplx.xowa.bldrs.infos.Xob_info_file;
import gplx.xowa.bldrs.infos.Xob_info_session;
import gplx.xowa.wikis.data.tbls.Xowd_page_tbl;
import gplx.xowa.wikis.data.tbls.Xowd_text_tbl;
public class Xow_db_mgr {
private final Io_url wiki_root_dir;
private final String domain_str; // needed for generating new files; EX: en.wikipedia.org-text.ns.001.xowa
private final Ordered_hash hash_by_id = Ordered_hash_.New(); private final Xow_db_file_hash hash_by_tids = new Xow_db_file_hash();
private int db_id_next = 0;
public Xow_db_mgr(Io_url wiki_root_dir, String domain_str) {
this.wiki_root_dir = wiki_root_dir;
this.domain_str = domain_str;
}
public Xowd_core_db_props Props() {return props;} private Xowd_core_db_props props = Xowd_core_db_props.Test;
public Db_cfg_tbl Tbl__cfg() {return db__core.Tbl__cfg();}
public Xowd_page_tbl Tbl__page() {return db__core.Tbl__page();}
public Xow_db_file Db__core() {return db__core;} private Xow_db_file db__core;
public Xow_db_file Db__text() {return db__text;} private Xow_db_file db__text;
public Xow_db_file Db__html() {return db__html;} private Xow_db_file db__html;
public Xow_db_file Db__cat_core() {return db__cat_core;} private Xow_db_file db__cat_core;
public Xow_db_file Db__wbase() {return db__wbase;} private Xow_db_file db__wbase; public void Db__wbase_(Xow_db_file v) {db__wbase = v;}
public void Init_by_load(Io_url core_url) {
// clear lists
hash_by_id.Clear();
hash_by_tids.Clear();
// create core_conn / core_db
Db_conn core_conn = Db_conn_bldr.Instance.Get(core_url);
props = Xowd_core_db_props.Cfg_load(core_conn); // load props to get layout_text
Dbs__set_by_tid(Xow_db_file.Load(props, Xow_db_file_.Uid__core, Xow_db_file__core_.Core_db_tid(props.Layout_text()), core_url, Xob_info_file.Ns_ids_empty, Xob_info_file.Part_id_1st, Guid_adp_.Empty));
// load dbs from "xowa_db" tbl
Xow_db_file[] ary = db__core.Tbl__db().Select_all(props, core_url.OwnerDir());
int len = ary.length;
for (int i = 0; i < len; i++) {
Xow_db_file db = ary[i];
Dbs__set_by_tid(db);
Dbs__add(db);
}
}
public void Init_by_make(Xowd_core_db_props props, Xob_info_session info_session) {
this.props = props;
// save data
Xow_db_file core_db = Xow_db_file__core_.Make_core_db(props, info_session, wiki_root_dir, domain_str);
Dbs__set_by_tid(core_db);
Dbs__add_and_save(core_db);
props.Cfg_save(db__core.Tbl__cfg()); // NOTE: must save cfg now, especially zip_tid; latter will be reloaded after import is done;
}
public void Rls() {
int len = hash_by_id.Len();
for (int i = 0; i < len; i++) {
Xow_db_file db_file = (Xow_db_file)hash_by_id.Get_at(i);
db_file.Rls();
}
}
public int Dbs__len() {return hash_by_id.Len();}
public Xow_db_file Dbs__get_at(int i) {return (Xow_db_file)hash_by_id.Get_at(i);}
public Xow_db_file Dbs__get_by_id_or_fail(int id) {return (Xow_db_file)hash_by_id.Get_by_or_fail(id);}
public Xow_db_file Dbs__get_by_id_or_null(int id) {return (Xow_db_file)hash_by_id.Get_by(id);}
public Xow_db_file Dbs__get_by_tid_or_core(byte... tids_ary) {Xow_db_file rv = Dbs__get_by_tid_or_null(tids_ary); return rv == null ? db__core : rv;}
public Xow_db_file Dbs__get_by_tid_or_null(byte... tids_ary) {
int tids_len = tids_ary.length;
for (int i = 0; i < tids_len; ++i) {
byte tid = tids_ary[i];
Ordered_hash tid_dbs = hash_by_tids.Get_by_tid_or_null(tid); if (tid_dbs == null) continue;
int tid_dbs_len = tid_dbs.Len();
if (tid_dbs_len != 1) { // NOTE: occurs when multiple search imports fail; DATE:2016-04-04
Xoa_app_.Usr_dlg().Warn_many("", "", "expecting only 1 db for tid; tid=~{0} len=~{1} db_api=~{2}", tid, tid_dbs.Len(), db__core.Conn().Conn_info().Db_api());
}
return (Xow_db_file)tid_dbs.Get_at(tid_dbs_len - 1); // get last idx;
}
return null;
}
public Xow_db_file Dbs__assert_by_tid(byte tid) {
Xow_db_file rv = Dbs__get_by_tid_or_null(tid);
if (rv == null) {
rv = Dbs__make_by_tid(tid);
}
return rv;
}
public Ordered_hash Dbs__get_hash_by_tid(int tid) {return hash_by_tids.Get_by_tid_or_null((byte)tid);}
public Xow_db_file Dbs__make_by_tid(byte tid) {
int tid_idx = Get_tid_idx(hash_by_tids, tid);
return Dbs__make_by_tid(tid, Xob_info_file.Ns_ids_empty, tid_idx, Get_tid_name(tid_idx, tid));
}
public Xow_db_file Dbs__make_by_tid(byte tid, String ns_ids, int part_id, String file_name_suffix) {
return Dbs__make_by_id(db_id_next++, tid, ns_ids, part_id, file_name_suffix);
}
public Xow_db_file Dbs__make_by_id(int id, byte tid, String ns_ids, int part_id, String file_name_suffix) {
Io_url url = wiki_root_dir.GenSubFil(domain_str + file_name_suffix);
Xow_db_file rv = Xow_db_file.Make(db__core.Info_session(), props, id, tid, url, ns_ids, part_id, db__core.Url().NameAndExt(), Db_conn_bldr.Instance.New(url));
Dbs__add_and_save(rv);
Dbs__set_by_tid(rv);
return rv;
}
public Xow_db_file Dbs__remake_by_tid(byte tid) {
Dbs__delete_by_tid(tid);
return Dbs__make_by_tid(tid);
}
public void Dbs__delete_by_tid(byte... tids) {
int len = hash_by_id.Len();
for (int i = 0; i < len; ++i) {
Xow_db_file db = (Xow_db_file)hash_by_id.Get_at(i);
if (!Byte_.Match_any(db.Tid(), tids)) continue;
db.Rls();
Io_mgr.Instance.DeleteFil_args(db.Url()).MissingFails_off().Exec();
db.Cmd_mode_(Db_cmd_mode.Tid_delete);
}
db__core.Tbl__db().Commit_all(this);
// call init again to regen list of dbs
this.Init_by_load(db__core.Url());
}
public Xow_db_file Dbs__get_for_create(byte tid, int ns_id) {
Xow_db_file[] ary = Dbs__get_ary(tid, ns_id);
if (ary.length == 0) throw Err_.new_wo_type("no dbs exist; wiki=~{0} type=~{1}", domain_str, tid);
return ary[ary.length - 1];
}
public Xow_db_file[] Dbs__get_ary(byte tid, int ns_id) {
List_adp rv = List_adp_.New();
// loop all dbs
int len = this.Dbs__len();
for (int i = 0; i < len; i++) {
boolean add = false;
Xow_db_file db = this.Dbs__get_at(i);
switch (tid) {
// cat_link requested
case Xow_db_file_.Tid__cat_link:
switch (db.Tid()) {
case Xow_db_file_.Tid__core:
add = props.Layout_text().Tid_is_all_or_few(); // cat_link will be in "core" if "all" or "few" (-text, -html, -file)
break;
case Xow_db_file_.Tid__cat_link:
add = true;
break;
}
break;
// text requested
case Xow_db_file_.Tid__text:
switch (db.Tid()) {
case Xow_db_file_.Tid__core:
add = props.Layout_text().Tid_is_all(); // text will be in "core" if "all"
break;
case Xow_db_file_.Tid__text_solo: // EX: "en.wikipedia.org-text.xowa"
add = true; // text will be in db if solo;
break;
case Xow_db_file_.Tid__text: // EX: "en.wikipedia.org-text-ns.000.xowa"
int[] db_ns_ids = Int_ary_.Parse(db.Ns_ids(), "|"); // need to handle both "0" and "0|4"
for (int db_ns_id : db_ns_ids) {
if (db_ns_id == ns_id) {
add = true; // text will be in db if ns matches; EX: en.wikipedia.org-text-ns.014.xowa
break;
}
}
break;
}
break;
}
if (add)
rv.Add(db);
}
return (Xow_db_file[])rv.To_ary_and_clear(Xow_db_file.class);
}
public void Create_page(Xowd_page_tbl core_tbl, Xowd_text_tbl text_tbl, int page_id, int ns_id, byte[] ttl_wo_ns, boolean redirect, DateAdp modified_on, byte[] text_zip_data, int text_raw_len, int random_int, int text_db_id, int html_db_id) {
core_tbl.Insert_cmd_by_batch(page_id, ns_id, ttl_wo_ns, redirect, modified_on, text_raw_len, random_int, text_db_id, html_db_id, -1);
text_tbl.Insert_cmd_by_batch(page_id, text_zip_data);
}
private void Dbs__set_by_tid(Xow_db_file db) {
switch (db.Tid()) {
case Xow_db_file_.Tid__wiki_solo:
case Xow_db_file_.Tid__text_solo:
case Xow_db_file_.Tid__core : {db__core = db; if (props.Layout_text().Tid_is_all_or_few()) db__cat_core = db__text = db; break;}
case Xow_db_file_.Tid__text : {db__text = db; break;}
case Xow_db_file_.Tid__html_data : {db__html = db; break;}
case Xow_db_file_.Tid__wbase : {if (db__wbase == null) db__wbase = db; break;}
case Xow_db_file_.Tid__cat_core :
case Xow_db_file_.Tid__cat : {if (db__cat_core == null) db__cat_core = db; break;}
}
}
private void Dbs__add(Xow_db_file db_file) {
int db_id = db_file.Id();
hash_by_id.Add(db_id, db_file);
hash_by_tids.Add_or_new(db_file);
if (db_id >= db_id_next) // always set db_id_next to largest value in given set of dbs; EX: dbs=[0,1,10]; db_id_next should be 11
db_id_next = db_id + 1;
}
private void Dbs__add_and_save(Xow_db_file db_file) {
Dbs__add(db_file);
db__core.Tbl__db().Commit_all(this);
db_file.Info_file().Save(db_file.Tbl__cfg());
db_file.Info_session().Save(db_file.Tbl__cfg());
}
private int Get_tid_idx(Xow_db_file_hash hash, byte tid) {return hash.Count_of_tid(tid) + Int_.Base1;}
private static String Get_tid_name(int tid_idx, byte tid) {
String tid_name = Xow_db_file_.To_key(tid);
String tid_idx_str = "";
switch (tid) {
case Xow_db_file_.Tid__cat_core : break;
case Xow_db_file_.Tid__cat_link : tid_idx_str = "-db." + Int_.To_str_pad_bgn_zero(tid_idx, 3); break;
default : tid_idx_str = tid_idx == 1 ? "" : "-db." + Int_.To_str_pad_bgn_zero(tid_idx, 3); break;
}
return String_.Format("-{0}{1}.xowa", tid_name, tid_idx_str); // EX: en.wikipedia.org-text-001.sqlite3
}
// helper method for wikis to (a) init db_mgr; (b) load wiki.props; should probably be moved to more generic "wiki.Init_by_db()"
public static void Init_by_load(Xow_wiki wiki, Io_url core_url) {
wiki.Data__core_mgr().Init_by_load(core_url);
wiki.Props().Init_by_load(wiki.App(), wiki.Data__core_mgr().Tbl__cfg()); // load Main_page
}
}