001/*
002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.platform.importer.random;
021
022import java.io.IOException;
023import java.util.HashMap;
024import java.util.Map;
025import java.util.Random;
026
027import org.nuxeo.ecm.core.api.NuxeoException;
028
029/**
030 * Random text generator to be used for load testing
031 *
032 * @author Thierry Delprat
033 */
034public class RandomTextGenerator {
035
036    protected DictionaryHolder dictionaryHolder;
037
038    protected Map<String, String> paragraphCache = new HashMap<String, String>();
039
040    protected Map<String, String> pageCache = new HashMap<String, String>();
041
042    protected Map<String, String> blockCache = new HashMap<String, String>();
043
044    protected static final int PARAGRAPH_CACHE_SIZE = 100;
045
046    protected static final int PARAGRAPH_CACHE_HIT = 100;
047
048    protected static final int PAGE_CACHE_SIZE = 50;
049
050    protected static final int PAGE_CACHE_HIT = 30;
051
052    protected static final int BLOC_CACHE_SIZE = 30;
053
054    protected static final int BLOC_CACHE_HIT = 20;
055
056    protected static final int BLOC_SIZE = 10 * 1024;
057
058    protected static final int NB_WORDS_PER_LINE = 20;
059
060    protected static final int NB_LINES_PER_PARAGRAPH = 40;
061
062    protected static final int NB_PARAGRAPH_PER_PAGE = 8;
063
064    protected static final int NB_PAGE_PER_BLOC = 3;
065
066    protected Random generator;
067
068    public RandomTextGenerator(DictionaryHolder dictionary) {
069        dictionaryHolder = dictionary;
070        generator = new Random(System.currentTimeMillis());
071    }
072
073    protected int getTargetPageMaxSizeB() {
074        return (int) (1.2 * (BLOC_SIZE / NB_PAGE_PER_BLOC));
075    }
076
077    protected int getTargetParagraphMaxSizeB() {
078        return (int) (1.2 * (getTargetPageMaxSizeB() / NB_PARAGRAPH_PER_PAGE));
079    }
080
081    public String getRandomLine() {
082        int nbW = 10 + generator.nextInt(NB_WORDS_PER_LINE);
083        StringBuffer sb = new StringBuffer();
084
085        for (int i = 0; i < nbW; i++) {
086            sb.append(dictionaryHolder.getRandomWord());
087        }
088        sb.append(".\n");
089        return sb.toString();
090    }
091
092    public String generateParagraph() {
093        int nbL = 10 + generator.nextInt(NB_LINES_PER_PARAGRAPH);
094        StringBuffer sb = new StringBuffer();
095
096        int maxSize = getTargetParagraphMaxSizeB();
097
098        for (int i = 0; i < nbL; i++) {
099            sb.append(getRandomLine());
100            if (sb.length() > maxSize) {
101                break;
102            }
103        }
104        sb.append("\n\n");
105        return sb.toString();
106    }
107
108    public void prefilCache() {
109
110        try {
111            dictionaryHolder.init();
112        } catch (IOException e) {
113            throw new NuxeoException(e);
114        }
115
116        for (int i = 0; i < PARAGRAPH_CACHE_SIZE; i++) {
117            paragraphCache.put("P" + i, generateParagraph());
118        }
119
120        for (int i = 0; i < PAGE_CACHE_SIZE; i++) {
121            String page = generatePage();
122            pageCache.put("P" + i, page);
123        }
124
125        for (int i = 0; i < BLOC_CACHE_SIZE; i++) {
126            String page = generateBloc();
127            blockCache.put("B" + i, page);
128        }
129
130    }
131
132    public String getRandomParagraph() {
133        int rand = generator.nextInt();
134        int idx = generator.nextInt(PARAGRAPH_CACHE_SIZE);
135        String paragraph = null;
136        if (rand % PARAGRAPH_CACHE_HIT != 0) {
137            paragraph = paragraphCache.get("P" + idx);
138        }
139        if (paragraph == null) {
140            paragraph = generateParagraph();
141            paragraphCache.put("P" + idx, paragraph);
142        }
143        return paragraph;
144    }
145
146    public String generatePage() {
147        int nbL = generator.nextInt(NB_PARAGRAPH_PER_PAGE) + 1;
148        StringBuffer sb = new StringBuffer();
149
150        int maxTargetPageSize = getTargetPageMaxSizeB();
151        for (int i = 0; i < nbL; i++) {
152            sb.append(getRandomParagraph());
153            if (sb.length() > maxTargetPageSize) {
154                break;
155            }
156        }
157        sb.append("\n\n");
158        return sb.toString();
159    }
160
161    public String getRandomPage() {
162        int rand = generator.nextInt();
163        int idx = generator.nextInt(PAGE_CACHE_SIZE);
164        String page = null;
165        if (rand % PAGE_CACHE_HIT != 0) {
166            page = pageCache.get("P" + idx);
167        }
168        if (page == null) {
169            page = generatePage();
170            pageCache.put("P" + idx, page);
171        }
172        return page;
173    }
174
175    public String generateBloc() {
176        StringBuffer sb = new StringBuffer();
177
178        while (sb.length() < BLOC_SIZE) {
179            sb.append(getRandomPage());
180        }
181        return sb.toString();
182    }
183
184    public String getRandomBloc() {
185        int rand = generator.nextInt();
186        int idx = generator.nextInt(BLOC_CACHE_SIZE);
187        String bloc = null;
188        if (rand % BLOC_CACHE_HIT != 0) {
189            bloc = blockCache.get("B" + idx);
190        }
191        if (bloc == null) {
192            bloc = generateBloc();
193            blockCache.put("B" + idx, bloc);
194        }
195        return bloc;
196    }
197
198    public String getRandomText(int avSizeInK) {
199        StringBuffer sb = new StringBuffer();
200        int minSize = (int) (avSizeInK * 1024 * (0.8 + 0.4 * generator.nextFloat()));
201        while (sb.length() < (minSize - BLOC_SIZE)) {
202            String p = getRandomBloc();
203            sb.append(p);
204        }
205        while (sb.length() < minSize) {
206            String p = getRandomPage();
207            sb.append(p);
208        }
209        return sb.toString();
210    }
211
212    public String getRandomText() {
213        int sizeK = generator.nextInt(500) + 1;
214        return getRandomText(sizeK);
215    }
216
217}