/** * Replication Benchmarker * https://github.com/score-team/replication-benchmarker/ * Copyright (C) 2013 LORIA / Inria / SCORE Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package citi.treedoc; import java.util.*; public class TreedocIdFactory implements IdFactory<TreedocId> { long baseSiteId = 7; long siteId = baseSiteId; // should be set to a specific value int counter = 0; // private Random rand; static TreedocIdFactory factory; public static TreedocIdFactory getFactory() { if (factory == null) { factory = new TreedocIdFactory(); } return factory; } // private int newRandom( int l, int h) { // int n = h - l + 1; // if( n <= 0) // n = n-1; // return l + rand.nextInt( n); // } protected TreedocIdFactory() { // rand = new Random(); // rand.setSeed( 10); } private synchronized TreedocId createNew() { TreedocId id = new TreedocId(new TreedocDisambiguator(counter++, siteId)); return id; } private TreedocId createLeft(TreedocId t) { TreedocId id = new TreedocId(t, new TreedocDisambiguator(counter++, siteId)); int len = id.bs.length(); id.bs.clear(len - 1); id.bs.set(len); return id; } private TreedocId createRight(TreedocId t) { TreedocId id = new TreedocId(t, new TreedocDisambiguator(counter++, siteId)); int len = id.bs.length(); id.bs.set(len); return id; } private synchronized List<TreedocId> createNew(int n, TreedocId base) { List<TreedocId> l = new ArrayList<TreedocId>(); TreedocId id = new TreedocId(base, new TreedocDisambiguator(counter++, siteId)); l.add(id); n--; outloop: for (int level = 1; n > 0; level++) { boolean left = true; for (int i = 0; i < l.size() && n > 0; i++) { TreedocId t = l.get(i); if (left) { id = createLeft(t); l.add(i, id); n--; left = false; } else { id = createRight(t); i++; l.add(i, id); i++; n--; left = true; } } } return l; } @Override public synchronized List<TreedocId> createNew(TreedocId before, TreedocId after, int n, int siteId) { if (siteId >= 0) { this.siteId = siteId; } else { this.siteId = baseSiteId; } if (before == null && after == null) { return createNew(n, createNew()); } else if (before == null) { return createNew(n, createLeft(after)); } else if (after == null) { return createNew(n, createRight(before)); } else { return doCreateNew(n, before, after); } } @Override public synchronized TreedocId createNew(TreedocId before, TreedocId after, int siteId) { if (siteId >= 0) { this.siteId = siteId; } else { this.siteId = baseSiteId; } if (before == null && after == null) { return createNew(); } else if (before == null) { return doCreateNewHead(after); } else if (after == null) { return doCreateNewTail(before); } else { return doCreateNew(before, after); } } private boolean smaller(TreedocId p, TreedocId q) { int i = 0; for (; i < p.bs.length() - 1; i++) { if (i >= q.bs.length() - 1) { return !p.bs.get(i); } if (p.bs.get(i) == q.bs.get(i)) { continue; } return !p.bs.get(i); } if (i == q.bs.length() - 1) { return false; } return q.bs.get(i); } private TreedocId doCreateNewHead(TreedocId q) { TreedocId id = new TreedocId(new TreedocDisambiguator(counter++, siteId)); if (q.l != null) { id.l = new Disambiguators[q.l.length]; System.arraycopy(q.l, 0, id.l, 0, q.l.length); } int llen = id.bs.length() - 1; int qlen = q.bs.length() - 1; id.bs.clear(llen); q.bs.clear(qlen); id.bs.or(q.bs); q.bs.set(qlen); int idlen = llen; if (idlen < qlen) { idlen = qlen; } id.bs.set(idlen + 1); return id; } private TreedocId doCreateNewTail(TreedocId p) { TreedocId id = new TreedocId(new TreedocDisambiguator(counter++, siteId)); if (p.l != null) { id.l = new Disambiguators[p.l.length]; System.arraycopy(p.l, 0, id.l, 0, p.l.length); } id.bs.or(p.bs); id.bs.set(id.bs.length()); return id; } private TreedocId doCreateNew(TreedocId p, TreedocId q) { // boolean ok = true; // if( counter > 90) { // ok = true; // } TreedocId m = doCreateNew0(p, q); if (!smaller(p, m)) { throw new RuntimeException("create error"); // ok = false; // smaller(p,m); } if (!smaller(m, q)) { throw new RuntimeException("create error"); // ok = false; // smaller(m,q); } if (m.bs.length() == 0) { throw new RuntimeException("create error"); // ok = false; // smaller(m,q); } // if( ! ok) { // counter--; // m = doCreateNew0( p, q); // } return m; } private TreedocId doCreateNew0(TreedocId p, TreedocId q) { int i = 0; int lenP = p.bs.length() - 1; int lenQ = q.bs.length() - 1; TreedocId r = new TreedocId(new TreedocDisambiguator(counter++, siteId)); for (i = 0; i < lenP && i < lenQ; i++) { if (p.bs.get(i) != q.bs.get(i)) { r.bs.set(i); return r; } r.bs.set(i, p.bs.get(i)); } if (lenP == lenQ + 1) { r.bs.set(i, p.bs.get(i)); i++; r.bs.set(i); r.bs.set(i + 1); return r; } if (lenP + 1 == lenQ) { r.bs.set(i, q.bs.get(i)); i++; r.bs.clear(i); r.bs.set(i + 1); return r; } if (lenP > lenQ + 1) { for (;;) { r.bs.set(i, p.bs.get(i)); i++; if (i == lenP) { break; } if (p.bs.get(i) == false) { break; } } if (i == lenP) { r.bs.set(i++); } r.bs.set(i); return r; } if (lenP + 1 < lenQ) { for (;;) { r.bs.set(i, q.bs.get(i)); i++; if (i == lenQ) { break; } if (q.bs.get(i) == true) { break; } } if (i == lenQ) { r.bs.clear(i++); } r.bs.set(i); return r; } System.out.println(p); System.out.println(q); System.out.println(r); throw new RuntimeException("not expected:" + lenP + ":" + lenQ); } private List<TreedocId> doCreateNew(int n, TreedocId p, TreedocId q) { boolean ok = true; List<TreedocId> m = doCreateNew0(n, p, q); if (!smaller(p, m.get(0))) { throw new RuntimeException("create error"); // ok = false; // smaller( p, m.get( 0)); } for (int i = 1; i < m.size(); i++) { if (!smaller(m.get(i - 1), m.get(i))) { throw new RuntimeException("create error"); // ok = false; // smaller(p,m); } } if (!smaller(m.get(m.size() - 1), q)) { // throw new RuntimeException( "create error"); ok = false; smaller(m.get(m.size() - 1), q); } if (!ok) { counter--; m = doCreateNew0(n, p, q); } return m; } private List<TreedocId> doCreateNew0(int n, TreedocId p, TreedocId q) { int i = 0; int lenP = p.bs.length() - 1; int lenQ = q.bs.length() - 1; for (i = 0; i < lenP && i < lenQ; i++) { if (p.bs.get(i) != q.bs.get(i)) { if (lenP < lenQ) { return createNew(n, createRight(p)); } else { return createNew(n, createLeft(q)); } } } if (lenP == lenQ + 1) { return createNew(n, createRight(p)); } if (lenP + 1 == lenQ) { return createNew(n, createLeft(q)); } if (lenP > lenQ + 1) { TreedocId id = createLeft(q); while (!smaller(p, id)) { id = createRight(id); } id = createRight(id); return createNew(n, id); } if (lenP + 1 < lenQ) { TreedocId id = createRight(p); while (!smaller(id, q)) { id = createLeft(id); } id = createLeft(id); return createNew(n, id); } System.out.println(p); System.out.println(q); throw new RuntimeException("not expected:" + lenP + ":" + lenQ); } }