mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
'v3.7.4.1'
This commit is contained in:
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.caches; import gplx.*; import gplx.core.*;
|
||||
import org.junit.*; import gplx.core.envs.*;
|
||||
public class GfoCacheMgr_tst {
|
||||
@Before public void init() {fxt = new GfoCacheMgr_fxt();} GfoCacheMgr_fxt fxt;
|
||||
@Test public void teardown() {Env_.TickCount_Test = -1;}
|
||||
@Test public void Basic() {fxt.run_Add("a").Expd_curSize_(1).Expd_itms_("a").tst();}
|
||||
// @Test public void Reduce() {fxt.run_Add("a", "b", "c", "d", "e").Expd_curSize_(3).Expd_itms_("c", "d", "e").tst();}
|
||||
// @Test public void Access() {fxt.run_Add("a", "b", "c", "d").run_Get("b", "a").run_Add("e").Expd_curSize_(3).Expd_itms_("b", "a", "e").tst();}
|
||||
// @Test public void Sizes() {fxt.run_Add("abc", "d", "e").Expd_curSize_(2).Expd_itms_("d", "e").tst();}
|
||||
}
|
||||
class GfoCacheMgr_fxt {
|
||||
Gfo_cache_mgr mgr = new Gfo_cache_mgr().Max_size_(4).Reduce_by_(2);
|
||||
public GfoCacheMgr_fxt() {
|
||||
Env_.TickCount_Test = 1;
|
||||
}
|
||||
public GfoCacheMgr_fxt run_Add(String... ary) {
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
String s = ary[i];
|
||||
mgr.Add(Bry_.new_u8(s), new GfoCacheItm_mock(s), String_.Len(s));
|
||||
Env_.TickCount_Test++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public GfoCacheMgr_fxt run_Get(String... ary) {
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
String s = ary[i];
|
||||
mgr.Get_by_key(Bry_.new_u8(s));
|
||||
Env_.TickCount_Test++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public GfoCacheMgr_fxt Expd_curSize_(int v) {expd_curSize = v; return this;} private int expd_curSize = -1;
|
||||
public GfoCacheMgr_fxt Expd_itms_(String... v) {expd_itms = v; return this;} private String[] expd_itms;
|
||||
public GfoCacheMgr_fxt tst() {
|
||||
if (expd_curSize != -1) Tfds.Eq(expd_curSize, mgr.Cur_size(), "curSize");
|
||||
if (expd_itms != null) {
|
||||
String[] actl = new String[mgr.Count()];
|
||||
for (int i = 0; i < actl.length; i++)
|
||||
actl[i] = ((GfoCacheItm_mock)mgr.Get_at(i)).S();
|
||||
Tfds.Eq_ary_str(expd_itms, actl, "itms");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class GfoCacheItm_mock implements Rls_able {
|
||||
public void Rls() {}
|
||||
public String S() {return s;} private String s;
|
||||
public GfoCacheItm_mock(String s) {this.s = s;}
|
||||
}
|
||||
46
400_xowa/src/gplx/core/caches/Gfo_cache_data.java
Normal file
46
400_xowa/src/gplx/core/caches/Gfo_cache_data.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.caches; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.envs.*;
|
||||
class Gfo_cache_data implements gplx.CompareAble, Rls_able {
|
||||
private int count = 0;
|
||||
public Gfo_cache_data(byte[] key, Rls_able val, int size) {
|
||||
this.key = key; this.val = val;
|
||||
this.size = size;
|
||||
this.count = 1;
|
||||
}
|
||||
public byte[] Key() {return key;} private final byte[] key;
|
||||
public Rls_able Val() {return val;} private Rls_able val;
|
||||
public int Size() {return size;} private int size;
|
||||
|
||||
public Object Val_and_update() {
|
||||
++count;
|
||||
return val;
|
||||
}
|
||||
public void Val_(Rls_able val, int size) {
|
||||
this.val = val;
|
||||
this.size = size;
|
||||
}
|
||||
public int compareTo(Object obj) {
|
||||
Gfo_cache_data comp = (Gfo_cache_data)obj;
|
||||
return -Long_.Compare(count, comp.count); // "-" to sort most-recent first
|
||||
}
|
||||
public void Rls() {
|
||||
val.Rls();
|
||||
}
|
||||
}
|
||||
@@ -16,27 +16,71 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.caches; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.consoles.*; import gplx.core.envs.*;
|
||||
public class Gfo_cache_mgr {
|
||||
private Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
private Ordered_hash recent = Ordered_hash_.New_bry();
|
||||
public int Max_size() {return max_size;} public Gfo_cache_mgr Max_size_(int v) {max_size = v; return this;} private int max_size;
|
||||
public int Reduce_by() {return reduce_by;} public Gfo_cache_mgr Reduce_by_(int v) {reduce_by = v; return this;} private int reduce_by;
|
||||
public int Cur_size() {return cur_size;} private int cur_size;
|
||||
public int Count() {return hash.Count();}
|
||||
public void Clear() {hash.Clear(); recent.Clear(); cur_size = 0;}
|
||||
@gplx.Internal protected Object Get_at(int i) {
|
||||
private final Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
private final List_adp tmp_delete = List_adp_.New();
|
||||
public int Cur_size() {return cur_size;} private int cur_size;
|
||||
public int Max_size() {return max_size;} public Gfo_cache_mgr Max_size_(int v) {max_size = v; return this;} private int max_size;
|
||||
public int Reduce_by() {return reduce_by;} public Gfo_cache_mgr Reduce_by_(int v) {reduce_by = v; return this;} private int reduce_by;
|
||||
public void Clear() {
|
||||
synchronized (tmp_delete) {
|
||||
hash.Clear();
|
||||
cur_size = 0;
|
||||
}
|
||||
}
|
||||
public Object Get_by_key(byte[] key) {
|
||||
Object o = hash.Get_by(key);
|
||||
return o == null ? null : ((Gfo_cache_data)o).Val_and_update();
|
||||
}
|
||||
public void Add_replace(byte[] key, Rls_able val, int size) {
|
||||
Object o = hash.Get_by(key);
|
||||
if (o == null)
|
||||
Add(key, val, size);
|
||||
else {
|
||||
Gfo_cache_data itm = (Gfo_cache_data)o;
|
||||
synchronized (itm) {
|
||||
cur_size -= itm.Size();
|
||||
cur_size += size;
|
||||
itm.Val_(val, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Add(byte[] key, Rls_able val, int size) {
|
||||
synchronized (tmp_delete) {
|
||||
if (hash.Has(key)) return; // THREAD: since Get is not locked, it's possible to Add the same item twice
|
||||
cur_size += size;
|
||||
Gfo_cache_data itm = new Gfo_cache_data(key, val, size);
|
||||
hash.Add(key, itm);
|
||||
if (cur_size > max_size) this.Reduce();
|
||||
}
|
||||
}
|
||||
private void Reduce() {
|
||||
hash.Sort();
|
||||
int len = hash.Len();
|
||||
int list_size = 0;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_cache_data itm = (Gfo_cache_data)hash.Get_at(i);
|
||||
int new_size = list_size + itm.Size();
|
||||
if (new_size > reduce_by)
|
||||
tmp_delete.Add(itm);
|
||||
else
|
||||
list_size = new_size;
|
||||
}
|
||||
this.cur_size = list_size;
|
||||
len = tmp_delete.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_cache_data itm = (Gfo_cache_data)tmp_delete.Get_at(i);
|
||||
hash.Del(itm.Key());
|
||||
}
|
||||
tmp_delete.Clear();
|
||||
}
|
||||
public int Test__len() {return hash.Len();}
|
||||
public Object Test__get_at(int i) {
|
||||
Gfo_cache_data rv = (Gfo_cache_data)hash.Get_at(i);
|
||||
return rv.Val();
|
||||
}
|
||||
public Object Get_by_key(byte[] key) {
|
||||
Object o = hash.Get_by(key); if (o == null) return null;
|
||||
Gfo_cache_data rv = (Gfo_cache_data)o;
|
||||
rv.Timestamp_update();
|
||||
Object recent_itm = recent.Get_by(key);
|
||||
if (recent_itm == null) recent.Add(key, rv);
|
||||
return rv.Val();
|
||||
}
|
||||
// NOTE: not called yet
|
||||
/*
|
||||
public void Del(byte[] key) {
|
||||
Object o = hash.Get_by(key); if (o == null) return;
|
||||
Gfo_cache_data itm = (Gfo_cache_data)o;
|
||||
@@ -44,80 +88,5 @@ public class Gfo_cache_mgr {
|
||||
hash.Del(itm.Key());
|
||||
itm.Rls();
|
||||
}
|
||||
public void Add_replace(byte[] key, Rls_able val, int size) {
|
||||
// Del(key);
|
||||
// Add(key, val, size);
|
||||
Object o = hash.Get_by(key);
|
||||
if (o == null)
|
||||
Add(key, val, size);
|
||||
else {
|
||||
Gfo_cache_data itm = (Gfo_cache_data)o;
|
||||
cur_size -= itm.Size();
|
||||
cur_size += size;
|
||||
itm.Replace(val, size);
|
||||
}
|
||||
}
|
||||
public void Add(byte[] key, Rls_able val, int size) {
|
||||
// if (cur_size + size > 600000000) ReduceCache();
|
||||
cur_size += size;
|
||||
// ++cur_size;
|
||||
Gfo_cache_data itm = new Gfo_cache_data(key, val, size);
|
||||
hash.Add(key, itm);
|
||||
}
|
||||
public void Reduce_recent() {
|
||||
// Console_adp__sys.Instance.WriteLine("reducing");
|
||||
int len = recent.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfo_cache_data itm = (Gfo_cache_data)recent.Get_at(i);
|
||||
itm.Rls(); // releases root
|
||||
}
|
||||
recent.Clear();
|
||||
}
|
||||
public void Reduce_cache() {
|
||||
Console_adp__sys.Instance.Write_str_w_nl("compacting:");
|
||||
// hash.Sort();
|
||||
// int len = hash.Count();
|
||||
// List_adp deleted = List_adp_.New();
|
||||
// int deleted_size = 0, deleted_count = 0;
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// Gfo_cache_data itm = (Gfo_cache_data)hash.Get_at(i);
|
||||
// int new_deleted_size = deleted_size + 1;//itm.Size();
|
||||
// if (new_deleted_size > 4000 && deleted_count > 0) break;
|
||||
// deleted.Add(itm);
|
||||
// deleted_count++;
|
||||
// deleted_size = new_deleted_size;
|
||||
// }
|
||||
// len = deleted.Count();
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// Gfo_cache_data itm = (Gfo_cache_data)deleted.Get_at(i);
|
||||
// cur_size --;
|
||||
// hash.Del(bry_ref.Val_(itm.Key()));
|
||||
// itm.Rls();
|
||||
// }
|
||||
// deleted.Clear();
|
||||
|
||||
int len = hash.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfo_cache_data itm = (Gfo_cache_data)hash.Get_at(i);
|
||||
// hash.Del(bry_ref.Val_(itm.Key()));
|
||||
itm.Rls();
|
||||
}
|
||||
}
|
||||
}
|
||||
class Gfo_cache_data implements gplx.CompareAble, Rls_able {
|
||||
public Gfo_cache_data(byte[] key, Rls_able val, int size) {this.key = key; this.val = val; this.size = size; this.timestamp = Env_.TickCount();}
|
||||
public byte[] Key() {return key;} private byte[] key;
|
||||
public Rls_able Val() {return val;} private Rls_able val;
|
||||
public int Size() {return size;} private int size;
|
||||
public void Replace(Rls_able val, int size) {this.val = val; this.size = size;}
|
||||
public long Timestamp() {return timestamp;} public void Timestamp_update() {timestamp = Env_.TickCount();} private long timestamp;
|
||||
public int compareTo(Object obj) {
|
||||
Gfo_cache_data comp = (Gfo_cache_data)obj;
|
||||
return Long_.Compare(timestamp, comp.timestamp);
|
||||
}
|
||||
public void Rls() {
|
||||
val.Rls();
|
||||
// val = null;
|
||||
// key = null;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.caches; import gplx.*; import gplx.core.*;
|
||||
public class Gfo_cache_mgr_base {
|
||||
private Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
private final Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
public int Compress_max() {return compress_max;} public void Compress_max_(int v) {compress_max = v;} private int compress_max = 16;
|
||||
public int Compress_to() {return compress_to;} public void Compress_to_(int v) {compress_to = v;} private int compress_to = 8;
|
||||
protected Object Base_get_or_null(byte[] key) {
|
||||
|
||||
@@ -35,7 +35,7 @@ class Gfo_cache_itm_comparer implements gplx.core.lists.ComparerAble {
|
||||
Gfo_cache_itm rhs = (Gfo_cache_itm)rhsObj;
|
||||
return Long_.Compare(lhs.Touched(), rhs.Touched());
|
||||
}
|
||||
public static final Gfo_cache_itm_comparer Touched_asc = new Gfo_cache_itm_comparer();
|
||||
public static final Gfo_cache_itm_comparer Touched_asc = new Gfo_cache_itm_comparer();
|
||||
}
|
||||
class Io_url_exists_mgr {
|
||||
private gplx.core.caches.Gfo_cache_mgr_bry cache_mgr = new gplx.core.caches.Gfo_cache_mgr_bry();
|
||||
|
||||
73
400_xowa/src/gplx/core/caches/Gfo_cache_mgr_tst.java
Normal file
73
400_xowa/src/gplx/core/caches/Gfo_cache_mgr_tst.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.caches; import gplx.*; import gplx.core.*;
|
||||
import org.junit.*; import gplx.core.tests.*; import gplx.core.envs.*;
|
||||
public class Gfo_cache_mgr_tst {
|
||||
@Before public void init() {fxt.Clear();} private final Gfo_cache_mgr_fxt fxt = new Gfo_cache_mgr_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Exec__add("a");
|
||||
fxt.Test__cur_size(1);
|
||||
fxt.Test__itms("a");
|
||||
}
|
||||
@Test public void Reduce() {
|
||||
fxt.Exec__add("a", "b", "c", "d", "e");
|
||||
fxt.Test__cur_size(2);
|
||||
fxt.Test__itms("a", "b");
|
||||
}
|
||||
@Test public void Reduce_after_get() {
|
||||
fxt.Exec__add("a", "b", "c", "d");
|
||||
fxt.Exec__get("a", "c");
|
||||
fxt.Exec__add("e");
|
||||
fxt.Test__itms("a", "c");
|
||||
}
|
||||
}
|
||||
class Gfo_cache_mgr_fxt {
|
||||
private final Gfo_cache_mgr mgr = new Gfo_cache_mgr().Max_size_(4).Reduce_by_(2);
|
||||
public void Clear() {mgr.Clear();}
|
||||
public Gfo_cache_mgr_fxt Exec__add(String... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
String itm = ary[i];
|
||||
byte[] key = Bry_.new_u8(itm);
|
||||
mgr.Add(key, new Gfo_cache_itm_mock(itm), key.length);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Gfo_cache_mgr_fxt Exec__get(String... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
String itm = ary[i];
|
||||
mgr.Get_by_key(Bry_.new_u8(itm));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Gfo_cache_mgr_fxt Test__cur_size(int expd) {Gftest.Eq__int(expd, mgr.Cur_size(), "cur_size"); return this;}
|
||||
public Gfo_cache_mgr_fxt Test__itms(String... expd) {
|
||||
int len = mgr.Test__len();
|
||||
String[] actl = new String[len];
|
||||
for (int i = 0; i < len; ++i)
|
||||
actl[i] = ((Gfo_cache_itm_mock)mgr.Test__get_at(i)).Val();
|
||||
Gftest.Eq__ary(expd, actl, "itms");
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class Gfo_cache_itm_mock implements Rls_able {
|
||||
public Gfo_cache_itm_mock(String val) {this.val = val;}
|
||||
public String Val() {return val;} private String val;
|
||||
public void Rls() {}
|
||||
}
|
||||
Reference in New Issue
Block a user