├── .classpath ├── .gitignore ├── .project ├── CHANGES.txt ├── LICENSE.txt ├── README.md ├── RELEASE.txt ├── TODO ├── build.py ├── examples ├── githubsearch │ ├── .gitignore │ ├── Latin-dont-break-issues.rbbi │ ├── account-map.csv.20220722.verified │ ├── direct_load_all_github_issues.py │ ├── gitHistory.py │ ├── handle.py │ ├── index_github.py │ ├── load_commits.py │ ├── local_db.py │ ├── moreFacets.py │ ├── print_github_issues.py │ ├── production │ │ ├── README.md │ │ ├── push.py │ │ ├── restart.py │ │ ├── restartForever.py │ │ ├── runServer.py │ │ └── snapshot.py │ ├── search.py │ ├── server.py │ ├── static │ │ ├── about.html │ │ ├── bootstrap │ │ │ ├── css │ │ │ │ ├── bootstrap-responsive.css │ │ │ │ ├── bootstrap-responsive.min.css │ │ │ │ ├── bootstrap.css │ │ │ │ └── bootstrap.min.css │ │ │ ├── img │ │ │ │ ├── glyphicons-halflings-white.png │ │ │ │ └── glyphicons-halflings.png │ │ │ └── js │ │ │ │ ├── bootstrap.js │ │ │ │ └── bootstrap.min.js │ │ ├── css │ │ │ ├── autocomplete.css │ │ │ └── ui-lightness │ │ │ │ ├── images │ │ │ │ ├── animated-overlay.gif │ │ │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ │ │ ├── ui-bg_flat_10_000000_40x100.png │ │ │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ │ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ │ │ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ │ │ ├── ui-icons_222222_256x240.png │ │ │ │ ├── ui-icons_228ef1_256x240.png │ │ │ │ ├── ui-icons_ef8c08_256x240.png │ │ │ │ ├── ui-icons_ffd27a_256x240.png │ │ │ │ └── ui-icons_ffffff_256x240.png │ │ │ │ ├── jquery-ui-1.10.1.custom.css │ │ │ │ └── jquery-ui-1.10.1.custom.min.css │ │ ├── favicon.ico │ │ ├── img │ │ │ ├── 1star.gif │ │ │ ├── 2star.gif │ │ │ ├── 3star.gif │ │ │ ├── 4star.gif │ │ │ └── 5star.gif │ │ ├── js │ │ │ ├── jquery-1.9.1.js │ │ │ ├── jquery-ui-1.10.1.custom.js │ │ │ └── jquery-ui-1.10.1.custom.min.js │ │ ├── robots.txt │ │ └── select2 │ │ │ ├── select2.css │ │ │ ├── select2.js │ │ │ ├── select2.min.js │ │ │ ├── select2.png │ │ │ ├── select2x2.png │ │ │ └── spinner.gif │ ├── suggest.py │ ├── update_from_github.py │ └── util.py └── jirasearch │ ├── .gitignore │ ├── Latin-dont-break-issues.rbbi │ ├── README.txt │ ├── TODO │ ├── addIssuesToDB.py │ ├── createDB.py │ ├── dedup.py │ ├── gitHistory.py │ ├── handle.py │ ├── indexJira.py │ ├── list_issues.py │ ├── loadAllJiraIssues.py │ ├── loadMissingJiraIssues.py │ ├── load_all_github_issues.py │ ├── moreFacets.py │ ├── production │ ├── README.md │ ├── push.py │ ├── restart.py │ ├── restartForever.py │ ├── runServer.py │ └── snapshot.py │ ├── search.py │ ├── server.py │ ├── static │ ├── about.html │ ├── bootstrap │ │ ├── css │ │ │ ├── bootstrap-responsive.css │ │ │ ├── bootstrap-responsive.min.css │ │ │ ├── bootstrap.css │ │ │ └── bootstrap.min.css │ │ ├── img │ │ │ ├── glyphicons-halflings-white.png │ │ │ └── glyphicons-halflings.png │ │ └── js │ │ │ ├── bootstrap.js │ │ │ └── bootstrap.min.js │ ├── css │ │ ├── autocomplete.css │ │ └── ui-lightness │ │ │ ├── images │ │ │ ├── animated-overlay.gif │ │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ │ ├── ui-bg_flat_10_000000_40x100.png │ │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ │ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ │ ├── ui-icons_222222_256x240.png │ │ │ ├── ui-icons_228ef1_256x240.png │ │ │ ├── ui-icons_ef8c08_256x240.png │ │ │ ├── ui-icons_ffd27a_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ │ ├── jquery-ui-1.10.1.custom.css │ │ │ └── jquery-ui-1.10.1.custom.min.css │ ├── favicon.ico │ ├── img │ │ ├── 1star.gif │ │ ├── 2star.gif │ │ ├── 3star.gif │ │ ├── 4star.gif │ │ └── 5star.gif │ ├── js │ │ ├── jquery-1.9.1.js │ │ ├── jquery-ui-1.10.1.custom.js │ │ └── jquery-ui-1.10.1.custom.min.js │ ├── robots.txt │ └── select2 │ │ ├── select2.css │ │ ├── select2.js │ │ ├── select2.min.js │ │ ├── select2.png │ │ ├── select2x2.png │ │ └── spinner.gif │ ├── suggest.py │ └── util.py ├── scripts ├── esJSONToLuceneServerJSON.py ├── indexGeoNames.py ├── indexTaxis.py ├── indexWiki.py └── simDistributedQueue.py └── src ├── java └── org │ └── apache │ └── lucene │ └── server │ ├── Connection.java │ ├── Constants.java │ ├── DirectoryFactory.java │ ├── FieldDef.java │ ├── FieldDefBindings.java │ ├── FinishRequest.java │ ├── FromFileTermFreqIterator.java │ ├── GenFileUtil.java │ ├── GlobalState.java │ ├── IndexState.java │ ├── Jobs.java │ ├── MyIndexSearcher.java │ ├── NRTPrimaryNode.java │ ├── NRTReplicaNode.java │ ├── Pipe.java │ ├── PreHandle.java │ ├── QueryID.java │ ├── RemoteNodeConnection.java │ ├── SVJSONPassageFormatter.java │ ├── SearchQueue.java │ ├── Server.java │ ├── ServerCodec.java │ ├── ShardState.java │ ├── SimpleCopyJob.java │ ├── WholeMVJSONPassageFormatter.java │ ├── handlers │ ├── AddDocumentHandler.java │ ├── AddDocumentsHandler.java │ ├── AddReplicaHandler.java │ ├── AnalysisHandler.java │ ├── BuildSuggestHandler.java │ ├── BulkAddDocumentHandler.java │ ├── BulkAddDocumentsHandler.java │ ├── BulkCSVAddDocumentHandler.java │ ├── BulkCSVAddDocumentHandlerNonBinary.java │ ├── BulkUpdateDocumentHandler.java │ ├── BulkUpdateDocumentsHandler.java │ ├── CSVParser.java │ ├── CSVParserChars.java │ ├── CannedScorer.java │ ├── CommitHandler.java │ ├── CopyFilesHandler.java │ ├── CreateIndexHandler.java │ ├── CreateSnapshotHandler.java │ ├── DeleteAllDocumentsHandler.java │ ├── DeleteDocumentsHandler.java │ ├── DeleteIndexHandler.java │ ├── DocHandler.java │ ├── GetCommitUserDataHandler.java │ ├── Handler.java │ ├── HelpHandler.java │ ├── IndexStatusHandler.java │ ├── LinkNodeHandler.java │ ├── LiveSettingsHandler.java │ ├── NearestPointsHandler.java │ ├── NewNRTPointHandler.java │ ├── NodeToNodeHandler.java │ ├── RAMResourceLoaderWrapper.java │ ├── RefreshHandler.java │ ├── RegisterFieldsHandler.java │ ├── ReleaseSnapshotHandler.java │ ├── RollbackHandler.java │ ├── Search2Handler.java │ ├── SearchHandler.java │ ├── SendMeFilesHandler.java │ ├── SetCommitUserDataHandler.java │ ├── SettingsHandler.java │ ├── ShutdownHandler.java │ ├── StartIndexHandler.java │ ├── StatsHandler.java │ ├── StopIndexHandler.java │ ├── SuggestLookupHandler.java │ ├── UpdateDocumentHandler.java │ ├── UpdateSuggestHandler.java │ ├── WriteNRTPointHandler.java │ └── package.html │ ├── package.html │ ├── params │ ├── AnyType.java │ ├── BooleanType.java │ ├── EnumType.java │ ├── FloatType.java │ ├── IntType.java │ ├── ListType.java │ ├── LongType.java │ ├── OrType.java │ ├── Param.java │ ├── PolyType.java │ ├── Request.java │ ├── RequestFailedException.java │ ├── StringType.java │ ├── StructType.java │ ├── Type.java │ ├── WrapType.java │ └── package.html │ ├── plugins │ ├── Plugin.java │ └── package.html │ └── util │ └── MathUtil.java └── test └── org └── apache └── lucene └── server ├── MockPlugin-hello.txt ├── MockPlugin-lucene-server-plugin.properties ├── MockPlugin.java ├── RunServer.java ├── ServerBaseTestCase.java ├── TermFreqPayload.java ├── TestAddDocuments.java ├── TestAnalysis.java ├── TestBlockJoinQuery.java ├── TestBooleanFieldType.java ├── TestCommitUserData.java ├── TestCustomDirectory.java ├── TestDateTime.java ├── TestFacets.java ├── TestGrouping.java ├── TestHighlight.java ├── TestIndexing.java ├── TestLatLonPoint.java ├── TestNumericFields.java ├── TestPlugins.java ├── TestReplication.java ├── TestSearch.java ├── TestSearch2.java ├── TestServer.java ├── TestSettings.java ├── TestSimpleSpatial.java ├── TestSnapshots.java ├── TestSort.java ├── TestSuggest.java ├── TestVirtualFields.java ├── convertWiki.py ├── indexGeoNames.py ├── indexTaxis.py ├── indexWiki.py └── util └── TestMathUtil.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | data/ 3 | install/ 4 | lib/ 5 | lucene6x/ 6 | /eclipse-build/ 7 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | luceneserver 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | 0.1.1 2 | get scripts/indexTaxis.py working from an installation 3 | 4 | 0.1.0 on 8/1/2016 5 | first (binary) release 6 | -------------------------------------------------------------------------------- /RELEASE.txt: -------------------------------------------------------------------------------- 1 | 2 | make sure tests pass 3 | 4 | git add/commit/push all changes 5 | 6 | ./build.py package -version x.y.z 7 | 8 | install it, confirm scripts/indexTaxis.py works 9 | 10 | git tag -m "Release x.y.z" -a vx.y.z 11 | 12 | git push --tags 13 | 14 | after: 15 | - bump version constants in indexTaxis.py and build.py 16 | -------------------------------------------------------------------------------- /examples/githubsearch/.gitignore: -------------------------------------------------------------------------------- 1 | localconstants.py 2 | -------------------------------------------------------------------------------- /examples/githubsearch/moreFacets.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import sys 17 | sys.path.insert(0, '/home/changingbits/src/ui') 18 | 19 | import util 20 | import handle 21 | 22 | # Entry point in production: 23 | def application(environ, startResponse): 24 | return util.handleOnePage(environ, startResponse, handle.handleMoreFacets) 25 | -------------------------------------------------------------------------------- /examples/githubsearch/print_github_issues.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pickle 3 | import sqlite3 4 | import localconstants 5 | import json 6 | import datetime 7 | from datetime import timezone 8 | 9 | DB_PATH = localconstants.DB_PATH 10 | 11 | def connect_db_readonly(): 12 | path = f'file:{DB_PATH}?mode=ro' 13 | return sqlite3.connect(path, uri=True, timeout=120) 14 | 15 | def main(): 16 | db = connect_db_readonly() 17 | c = db.cursor() 18 | c2 = db.cursor() 19 | now = datetime.datetime.now(timezone.utc) 20 | open_pr_count = 0 21 | closed_pr_count = 0 22 | histo_by_days = {} 23 | 24 | print_full_pr = '-print_full_pr' in sys.argv 25 | if print_full_pr: 26 | sys.argv.remove('-print_full_pr') 27 | 28 | number = int(sys.argv[1]) 29 | 30 | if print_full_pr: 31 | pr_number = number 32 | blob = c.execute('SELECT pickle FROM issues WHERE key=?', (pr_number,)).fetchone()[0] 33 | issue, comments, events, reactions, timeline = pickle.loads(blob) 34 | print(f'\nISSUE:\n{json.dumps(issue, indent=2)}') 35 | print(f'\nCOMMENTS:\n{json.dumps(comments, indent=2)}') 36 | print(f'\nEVENTS:\n{json.dumps(events, indent=2)}') 37 | print(f'\nREACTIONS:\n{json.dumps(reactions, indent=2)}') 38 | print(f'\nTIMELINE:\n{json.dumps(timeline, indent=2)}') 39 | 40 | blob = c.execute('SELECT pickle FROM full_issue WHERE key=?', (pr_number,)).fetchone()[0] 41 | full_issue = pickle.loads(blob) 42 | print(f'\nFULL PULL_REQUEST:\n{json.dumps(full_issue, indent=2)}') 43 | 44 | 45 | sys.exit(0) 46 | 47 | for k, v in c.execute('SELECT key, pickle FROM issues').fetchall(): 48 | if k in ('last_update', 'page_upto'): 49 | continue 50 | 51 | issue, comments, events, reactions, timeline, full_pr, full_pr_comments, pr_reviews = pickle.loads(v) 52 | 53 | if issue['number'] == number: 54 | print(f'\nISSUE:\n{json.dumps(issue, indent=2)}') 55 | print(f'\nCOMMENTS (count={len(comments)}):') 56 | print_list('comment', comments) 57 | print(f'\nEVENTS (count={len(events)}):\n') 58 | print_list('event', events) 59 | print(f'\nREACTIONS (count={len(reactions)}):') 60 | print_list('reaction', reactions) 61 | print(f'\nTIMELINE (count={len(timeline)}):') 62 | print_list('timeline', timeline) 63 | print(f'\nFULL_PR:\n{json.dumps(full_pr, indent=2)}') 64 | print(f'\nFULL_PR_COMMENTS (count={len(full_pr_comments)}):') 65 | print_list('full_pr_comments', full_pr_comments) 66 | print(f'\nPR_REVIEWS (count={len(full_pr_comments)}):') 67 | print_list('pr_reviews', pr_reviews) 68 | 69 | if 'pull_request' in issue: 70 | if 'mergeable_state' in issue and issue['mergeable_state'] == 'unknown': 71 | print(f'unknown: {issue["html_url"]}') 72 | 73 | #print(f'\n issue {issue["number"]}\n{json.dumps(issue, indent=2)}') 74 | if False and len(events) > 0: 75 | print(f'\nissue {issue["number"]}') 76 | for event in events: 77 | # event types: https://docs.github.com/en/rest/overview/issue-event-types?apiVersion=2022-11-28 78 | print(f' {event["event"]}') 79 | if False and len(timeline) > 0: 80 | print(f'\nissue {issue["number"]}') 81 | for t in timeline: 82 | #print(f' {json.dumps(t, indent=2)}') 83 | print(f' {t["event"]}') 84 | print(f'{open_pr_count} open PRs; {closed_pr_count} closed PRs') 85 | 86 | entries = list(histo_by_days.items()) 87 | entries.sort() 88 | for days_age, count in entries: 89 | print(f'{days_age} days: {count}') 90 | 91 | def print_list(desc, l): 92 | 93 | for i, ent in enumerate(l): 94 | print(f' {desc} {i}:\n {json.dumps(ent, indent=4)}') 95 | 96 | if __name__ == '__main__': 97 | main() 98 | -------------------------------------------------------------------------------- /examples/githubsearch/production/README.md: -------------------------------------------------------------------------------- 1 | Silly scripts to push both UI and Lucene server changes to production 2 | and bounce the servers. -------------------------------------------------------------------------------- /examples/githubsearch/production/restart.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import time 17 | import urllib.request, urllib.error, urllib.parse 18 | import os 19 | import sys 20 | import shutil 21 | import signal 22 | 23 | sys.path.insert(0, '..') 24 | import localconstants 25 | 26 | PORT = localconstants.SERVER_PORT 27 | 28 | """ 29 | Production script to restart Lucene server and the UI. 30 | """ 31 | 32 | doReindex = '-reindex' in sys.argv 33 | doServer = '-server' in sys.argv 34 | 35 | def run(cmd): 36 | if os.system(cmd): 37 | raise RuntimeError('%s failed' % cmd) 38 | 39 | if doServer: 40 | print() 41 | print('Kill current runServer process') 42 | 43 | # kill runServer wrapper: 44 | found = False 45 | for line in os.popen('ps auxww | grep runServer.py | grep -v grep | grep -v /bin/sh').readlines(): 46 | pid = line.strip().split()[1] 47 | print(' kill server pid %s: %s' % (pid, line.strip())) 48 | if found: 49 | raise RuntimeError('found two pids!') 50 | try: 51 | run('kill -9 %d' % int(pid)) 52 | except: 53 | print('FAILED:') 54 | traceback.print_exc() 55 | found = True 56 | 57 | if not found: 58 | raise RuntimeError('could not find existing runServer.py process') 59 | 60 | print() 61 | print('Kill current java server process') 62 | 63 | # kill java process 64 | found = False 65 | for line in os.popen('ps auxww | grep java | grep server.Server | grep "ipPort localhost:%s" | grep -v grep | grep -v /bin/sh' % PORT).readlines(): 66 | pid = line.strip().split()[1] 67 | print(' kill server pid %s: %s' % (pid, line.strip())) 68 | if found: 69 | raise RuntimeError('found two pids!') 70 | try: 71 | run('kill -9 %d' % int(pid)) 72 | except: 73 | print('FAILED:') 74 | traceback.print_exc() 75 | found = True 76 | 77 | if not found: 78 | raise RuntimeError('could not find existing java server.Server process') 79 | 80 | print() 81 | print('Start new java server process') 82 | 83 | run(f'nohup {localconstants.PYTHON_EXE} -u runServer.py > {localconstants.GLOBAL_LOG_DIR}/luceneserver.log 2>&1 &') 84 | 85 | # Wait until server is really ready: 86 | server_log_file = f'{localconstants.GLOBAL_LOG_DIR}/luceneserver.log' 87 | while True: 88 | if os.path.exists(server_log_file): 89 | s = open(server_log_file, 'rb').read() 90 | if s.find(('listening on').encode('utf-8')) != -1: 91 | break 92 | time.sleep(1.0) 93 | 94 | print() 95 | print('Restart Apache httpd') 96 | 97 | run('sudo apachectl restart') 98 | 99 | print() 100 | print('Kill current Indexer') 101 | for line in os.popen('ps auxww | grep python | grep index_github.py | grep -v grep | grep -v ssh').readlines(): 102 | pid = line.strip().split()[1] 103 | print(' kill indexJira process pid %s [%s]' % (pid, line)) 104 | try: 105 | run('kill -9 %d' % int(pid)) 106 | except: 107 | pass 108 | 109 | if doReindex: 110 | extra = ' -reindex -delete' 111 | else: 112 | extra = '' 113 | 114 | print() 115 | print('Start new Indexer') 116 | os.chdir('..') 117 | run(f'nohup {localconstants.PYTHON_EXE} -u index_github.py -server localhost:{PORT} -nrt{extra} > {localconstants.STATE_LOG_DIR}/nrt.log 2>&1 &') 118 | 119 | print() 120 | print('Wait 5 seconds') 121 | time.sleep(5.0) 122 | -------------------------------------------------------------------------------- /examples/githubsearch/production/restartForever.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import datetime 4 | 5 | while True: 6 | mb = float(os.popen('ps axuww | grep org.apache.lucene.server.Server | grep -v grep').read().split()[5])/1024. 7 | if mb > 375.0: 8 | print('%s: now restart @ %.1f MB' % (datetime.datetime.now(), mb)) 9 | os.system('python3 -u restart.py') 10 | time.sleep(10.0) 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/githubsearch/production/runServer.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import threading 17 | import os 18 | import time 19 | import shutil 20 | import subprocess 21 | import sys 22 | import datetime 23 | import signal 24 | 25 | sys.path.insert(0, '..') 26 | 27 | import localconstants 28 | 29 | """ 30 | Python wrapper that spawns the Java lucene server process and restarts it if it dies. 31 | """ 32 | 33 | LUCENE_SERVER_VERSION = localconstants.LUCENE_SERVER_VERSION 34 | 35 | def readServerOutput(p, port, startupEvent, failureEvent, eachLine): 36 | while True: 37 | l = p.stdout.readline().decode('utf-8') 38 | if l == '': 39 | if not startupEvent.isSet(): 40 | failureEvent.set() 41 | startupEvent.set() 42 | raise RuntimeError('Server failed to start') 43 | else: 44 | break 45 | if 'listening on' in l: 46 | startupEvent.set() 47 | if eachLine is None: 48 | print('SVR: %s' % l.rstrip()) 49 | else: 50 | eachLine(l.rstrip()) 51 | 52 | class RunServer: 53 | 54 | """ 55 | Spawns java subprocess to run the Lucene server. 56 | """ 57 | 58 | def __init__(self, port, path, eachLine=None): 59 | self.port = port 60 | startupEvent = threading.Event() 61 | failureEvent = threading.Event() 62 | 63 | #VERSION = '4.2.0-ALPHA' 64 | #VERSION = '4.2-SNAPSHOT' 65 | 66 | HEAP = localconstants.HEAP 67 | 68 | # -agentlib:yjpagent=sampling,disablej2ee 69 | cmd = '%s -Xms%s -Xmx%s -Xss228k -cp "../luceneserver/lib/*" org.apache.lucene.server.Server -maxHTTPThreadCount 2 -ipPort localhost:%s -stateDir %s' % (localconstants.JAVA_EXE, HEAP, HEAP, port, localconstants.GLOBAL_STATE_PATH) 70 | 71 | print('SERVER CMD: %s' % cmd) 72 | 73 | self.p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 74 | 75 | t = threading.Thread(target=readServerOutput, args=(self.p, port, startupEvent, failureEvent, eachLine)) 76 | t.setDaemon(True) 77 | t.start() 78 | 79 | startupEvent.wait() 80 | if failureEvent.isSet(): 81 | sys.exit(0) 82 | 83 | def isAlive(self): 84 | return self.p.poll() is None 85 | 86 | def killServer(self): 87 | try: 88 | self.send('shutdown', {}) 89 | except: 90 | pass 91 | print('Find server pid to kill...') 92 | for line in os.popen('ps auxww | grep java | grep server.Server | grep "port %s" | grep -v grep' % self.port).readlines(): 93 | pid = line.strip().split()[1] 94 | print('Kill server pid %s' % pid) 95 | try: 96 | os.kill(int(pid), signal.SIGKILL) 97 | except: 98 | pass 99 | 100 | if __name__ == '__main__': 101 | 102 | while True: 103 | print() 104 | print('%s: START SERVER' % datetime.datetime.now()) 105 | svr = RunServer(localconstants.SERVER_PORT, localconstants.GLOBAL_INDICES_PATH) 106 | 107 | try: 108 | while True: 109 | time.sleep(.2) 110 | if not svr.isAlive(): 111 | print('NOT ALIVE') 112 | break 113 | finally: 114 | svr.killServer() 115 | 116 | time.sleep(1) 117 | 118 | -------------------------------------------------------------------------------- /examples/githubsearch/production/snapshot.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import os 17 | import datetime 18 | 19 | """ 20 | This runs on the production box and makes a full backup of src/ui in case we need to rollback. 21 | """ 22 | 23 | def run(cmd): 24 | if os.system(cmd): 25 | raise RuntimeError('%s failed' % cmd) 26 | 27 | # Take snapshot in case we need to fallback: 28 | os.chdir('../..') 29 | dt = datetime.datetime.now().date() 30 | upto = 0 31 | while True: 32 | if upto == 0: 33 | fileName = '../snapshots/github-ui.%04d%02d%02d.tar.bz2' % (dt.year, dt.month, dt.day) 34 | else: 35 | fileName = '../snapshots/github-ui.%04d%02d%02d-%d.tar.bz2' % (dt.year, dt.month, dt.day, upto) 36 | if not os.path.exists(fileName): 37 | print('snapshot to %s cwd=%s' % (fileName, os.getcwd())) 38 | run('tar cjf %s github-ui' % fileName) 39 | break 40 | upto += 1 41 | 42 | -------------------------------------------------------------------------------- /examples/githubsearch/search.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import io 17 | import gzip 18 | import traceback 19 | import sys 20 | sys.path.insert(0, '/home/ec2-user/src/github-ui') 21 | import util 22 | import handle 23 | 24 | # Entry point in production: 25 | def application(environ, startResponse): 26 | return util.handleOnePage(environ, startResponse, handle.handleQuery) 27 | -------------------------------------------------------------------------------- /examples/githubsearch/static/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 |
22 |
23 |
24 |   This site uses Apache Lucene, specifically this thin-wrapper HTTP server over Lucene, to search all Lucene GitHub issues and pull requests. See 25 | the Eating 26 | dog food with Lucene blog post and Jirasearch 2.0 dog food for details. The source code for indexing and searching GitHub issues is here. 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/githubsearch/static/bootstrap/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/bootstrap/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /examples/githubsearch/static/bootstrap/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/bootstrap/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/autocomplete.css: -------------------------------------------------------------------------------- 1 | #formWrap { 2 | padding:10px; position:absolute; float:left; background-color:#000; 3 | background:rgba(0,0,0,.5); -moz-border-radius:10px; 4 | -webkit-border-radius:10px; border-radius:10px; 5 | } 6 | #messageForm { 7 | width:326px; border:1px solid #666; background-color:#eee; 8 | } 9 | #messageForm fieldset { 10 | padding:0; margin:0; position:relative; border:none; 11 | background-color:#eee; 12 | } 13 | #messageForm legend { visibility:hidden; height:0; } 14 | #messageForm span { 15 | display:block; width:326px; padding:10px 0; margin:0 0 20px; 16 | text-indent:20px; background-color:#bbb; 17 | border-bottom:1px solid #333; font:18px Georgia, Serif; color:#fff; 18 | } 19 | #friends { 20 | width:274px; padding:3px 3px 0; margin:0 auto; 21 | border:1px solid #aaa; background-color:#fff; cursor:text; 22 | } 23 | #messageForm #to { 24 | width:30px; margin:0 0 2px 0; padding:0 0 3px; 25 | position:relative; top:0; float:left; border:none; 26 | } 27 | #messageForm input, #messageForm textarea { 28 | display:block; width:274px; padding:3px; margin:0 auto 20px; 29 | border:1px solid #aaa; 30 | } 31 | #messageForm label { 32 | display:block; margin:20px 0 3px; text-indent:22px; 33 | font:bold 11px Verdana, Sans-serif; color:#666; 34 | } 35 | #messageForm #toLabel { margin-top:0; } 36 | #messageForm button { float:right; margin:0 0 20px 0; } 37 | #messageForm #cancel { margin-right:20px; } 38 | #friends span { 39 | display:block; margin:0 3px 3px 0; padding:3px 20px 4px 8px; 40 | position:relative; float:left; background-color:#eee; 41 | border:1px solid #333; -moz-border-radius:7px; 42 | -webkit-border-radius:7px; border-radius:7px; color:#333; 43 | font:normal 11px Verdana, Sans-serif; 44 | } 45 | #friends span a { 46 | position:absolute; right:8px; top:2px; color:#666; 47 | font:bold 12px Verdana, Sans-serif; text-decoration:none; 48 | } 49 | #friends span a:hover { color:#ff0000; } 50 | .ui-menu .ui-menu-item { white-space:nowrap; padding:0 10px 0 0; } 51 | -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/animated-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/animated-overlay.gif -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-icons_228ef1_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-icons_228ef1_256x240.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-icons_ef8c08_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-icons_ef8c08_256x240.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-icons_ffd27a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-icons_ffd27a_256x240.png -------------------------------------------------------------------------------- /examples/githubsearch/static/css/ui-lightness/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/css/ui-lightness/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /examples/githubsearch/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/favicon.ico -------------------------------------------------------------------------------- /examples/githubsearch/static/img/1star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/img/1star.gif -------------------------------------------------------------------------------- /examples/githubsearch/static/img/2star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/img/2star.gif -------------------------------------------------------------------------------- /examples/githubsearch/static/img/3star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/img/3star.gif -------------------------------------------------------------------------------- /examples/githubsearch/static/img/4star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/img/4star.gif -------------------------------------------------------------------------------- /examples/githubsearch/static/img/5star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/img/5star.gif -------------------------------------------------------------------------------- /examples/githubsearch/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /search.py 3 | Disallow: /moreFacets.py 4 | Disallow: /suggest.py 5 | -------------------------------------------------------------------------------- /examples/githubsearch/static/select2/select2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/select2/select2.png -------------------------------------------------------------------------------- /examples/githubsearch/static/select2/select2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/select2/select2x2.png -------------------------------------------------------------------------------- /examples/githubsearch/static/select2/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/githubsearch/static/select2/spinner.gif -------------------------------------------------------------------------------- /examples/githubsearch/suggest.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import sys 17 | sys.path.insert(0, '/home/ec2-user/src/github-ui') 18 | import util 19 | import handle 20 | 21 | # Entry point in production: 22 | def application(environ, startResponse): 23 | return util.handleOnePage(environ, startResponse, handle.handleSuggest) 24 | -------------------------------------------------------------------------------- /examples/jirasearch/.gitignore: -------------------------------------------------------------------------------- 1 | localconstants.py 2 | -------------------------------------------------------------------------------- /examples/jirasearch/README.txt: -------------------------------------------------------------------------------- 1 | Simple Python scripts that pull Jira issues via the JSON search API, 2 | index them into luceneserver and offer a simple WSGI search UI to 3 | search/facet. 4 | 5 | loadAllJiraIssues.py -- run this once for a full export of all Jira issues 6 | 7 | createDB.py -- makes a local sqlite3 DB from the above issues loaded 8 | 9 | indexJira.py -- indexes all issues (-reindex -delete), and also does nrt build (-nrt) 10 | 11 | -------------------------------------------------------------------------------- /examples/jirasearch/TODO: -------------------------------------------------------------------------------- 1 | use renderedFields instead? this translates jira markup to HTML 2 | 3 | hmm is point-in-time searcher version not working! 4 | 5 | better handling of renamed issues 6 | 7 | are we getting dup suggestions w/ rename? 8 | 9 | org.this.that is not splitting into tokens!! 10 | 11 | lucene smoke doesn't highlight lucene in suggestions? 12 | 13 | remove isDev/prod/isMike? 14 | 15 | NRT is failing to show new comments? 16 | 17 | grep through production logs for exeptions! 18 | 19 | why does "bens" make bogus suggestions? 20 | 21 | search for 7462 SHOULD have found LUCENE-7174, like it does in production now 22 | 23 | how come number search e.g. 7462 does not highlight the issue title? 24 | 25 | annoyingly, the Jira query process does NOT count a new commit on an issue as updating its timestamp 26 | 27 | is NRT indexer not seeing newly created issues? 28 | 29 | merge the missed issues back into allIssues.txt in /lucenedata 30 | 31 | is there a faster bulk export? 32 | - should i re-do w/ rendering and use html strip char factory to get good final inch highlighting somehow... -------------------------------------------------------------------------------- /examples/jirasearch/addIssuesToDB.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import json 17 | import sqlite3 18 | import pickle 19 | import os 20 | import sys 21 | import localconstants 22 | import datetime 23 | 24 | """ 25 | Apply a set of issues from an issues.txt file to the sqlite3 DB used by 26 | indexJira.py for NRT updates. 27 | """ 28 | 29 | db = sqlite3.connect(localconstants.DB_PATH) 30 | c = db.cursor() 31 | with open(sys.argv[1], 'rb') as f: 32 | while True: 33 | l = f.readline() 34 | if l == b'': 35 | break 36 | i = l.find(b':') 37 | key = l[:i] 38 | value = l[i+1:].strip() 39 | c.execute('REPLACE INTO issues (key, body) VALUES (?, ?)', (key, pickle.dumps(json.loads(value.decode('utf-8'))))) 40 | db.commit() 41 | -------------------------------------------------------------------------------- /examples/jirasearch/createDB.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import json 17 | import sqlite3 18 | import pickle 19 | import os 20 | import sys 21 | import localconstants 22 | import datetime 23 | 24 | """ 25 | One time conversion, to turn allIssues.txt (exported via 26 | loadAllJiraIssues) -> sqlite3 DB used by indexJira.py for NRT updates. 27 | """ 28 | 29 | print('Building DB %s...' % localconstants.DB_PATH) 30 | 31 | if os.path.exists(localconstants.DB_PATH): 32 | os.remove(localconstants.DB_PATH) 33 | 34 | db = sqlite3.connect(localconstants.DB_PATH) 35 | c = db.cursor() 36 | c.execute('DROP TABLE IF EXISTS issues') 37 | c.execute('CREATE TABLE IF NOT EXISTS issues (key text PRIMARY KEY, body text)') 38 | c.execute('CREATE UNIQUE INDEX idx_issues_key ON issues(key)') 39 | 40 | c.execute('CREATE TABLE users (login TEXT UNIQUE PRIMARY KEY, pickle BLOB)') 41 | c.execute('CREATE TABLE full_issue (key TEXT UNIQUE PRIMARY KEY, pickle BLOB)') 42 | 43 | with open('/lucenedata/jirasearch/allIssues.20161017.txt', 'rb') as f: 44 | while True: 45 | l = f.readline() 46 | if l == b'': 47 | break 48 | i = l.find(b':') 49 | key = l[:i] 50 | value = l[i+1:].strip() 51 | c.execute('INSERT INTO issues (key, body) VALUES (?, ?)', (key, pickle.dumps(json.loads(value.decode('utf-8'))))) 52 | c.execute('CREATE TABLE IF NOT EXISTS lastUpdate (lastUpdate text)') 53 | c.execute('INSERT INTO lastUpdate VALUES (?)', (pickle.dumps(datetime.datetime(year=2016, month=10, day=17)),)) 54 | db.commit() 55 | -------------------------------------------------------------------------------- /examples/jirasearch/dedup.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | """ 17 | Silly tool necessary if your one-time run of loadAllJiraIssues.py crashed and you had to restart it and it loaded some duplicate issues into allIssues.txt 18 | """ 19 | 20 | with open('allIssues.txt', 'rb') as f, open('allIssues.dedup.txt', 'wb') as fOut: 21 | seen = set() 22 | while True: 23 | l = f.readline() 24 | if l == b'': 25 | break 26 | i = l.find(b':') 27 | key = l[:i] 28 | if key not in seen: 29 | seen.add(key) 30 | fOut.write(l) 31 | else: 32 | print('skip dup %s' % key) 33 | -------------------------------------------------------------------------------- /examples/jirasearch/list_issues.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | import pickle 3 | 4 | DB_PATH = 'github_issues.db' 5 | 6 | db = sqlite3.connect(DB_PATH) 7 | c = db.cursor() 8 | 9 | issues = c.execute('SELECT pickle FROM issues WHERE key NOT IN ("last_update", "page_upto")').fetchall() 10 | count = 0 11 | for issue in issues: 12 | issue, comments, events, reactions, timeline = pickle.loads(issue[0]) 13 | print(f'issue {issue["number"]}\n {len(comments)} comments') 14 | count += 1 15 | print(f'{count} issues') 16 | -------------------------------------------------------------------------------- /examples/jirasearch/moreFacets.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | #import sys 17 | #sys.path.insert(0, '/home/changingbits/src/ui') 18 | import util 19 | import handle 20 | 21 | # Entry point in production: 22 | def application(environ, startResponse): 23 | return util.handleOnePage(environ, startResponse, handle.handleMoreFacets) 24 | -------------------------------------------------------------------------------- /examples/jirasearch/production/README.md: -------------------------------------------------------------------------------- 1 | Silly scripts to push both UI and Lucene server changes to production 2 | and bounce the servers. -------------------------------------------------------------------------------- /examples/jirasearch/production/push.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import traceback 17 | import sys 18 | import time 19 | import urllib.request, urllib.error, urllib.parse 20 | import os 21 | import shutil 22 | import signal 23 | import runServer 24 | 25 | sys.path.insert(0, '..') 26 | import localconstants 27 | 28 | def run(cmd): 29 | if os.system(cmd): 30 | raise RuntimeError('%s failed; cwd=%s' % (cmd, os.getcwd())) 31 | 32 | if len(sys.argv) == 1: 33 | doServer = True 34 | doUI = True 35 | doReindex = False 36 | else: 37 | doServer = False 38 | doUI = False 39 | doReindex = False 40 | 41 | for arg in sys.argv[1:]: 42 | if arg == '-ui': 43 | doUI = True 44 | elif arg == '-server': 45 | doServer = True 46 | elif arg == '-reindex': 47 | doReindex = True 48 | else: 49 | raise RuntimeError('unknown arg %s' % arg) 50 | 51 | #userHost = 'changingbits@web504.webfaction.com' 52 | userHost = 'ec2-user@jirasearch.mikemccandless.com' 53 | #userHost = 'mike@10.17.4.12' 54 | sshIdent = '' 55 | #sshIdent = '-i /home/mike/.ssh/aws_changingbits.pem' 56 | 57 | print() 58 | print('Snapshot') 59 | run('ssh -t %s %s "cd src/jira-ui/production; python3 -u snapshot.py"' % (sshIdent, userHost)) 60 | 61 | if doServer: 62 | serverDistPath = '/l/luceneserver/build/luceneserver-%s.zip' % localconstants.LUCENE_SERVER_VERSION 63 | print() 64 | print('Copy %s' % serverDistPath) 65 | run('scp %s %s %s:src/jira-ui' % (sshIdent, serverDistPath, userHost)) 66 | run('ssh %s %s "cd src/jira-ui; rm -rf luceneserver; unzip luceneserver-%s.zip; mv luceneserver-%s luceneserver; rm luceneserver-%s.zip"' % (sshIdent, userHost, localconstants.LUCENE_SERVER_VERSION, localconstants.LUCENE_SERVER_VERSION, localconstants.LUCENE_SERVER_VERSION)) 67 | 68 | if doUI: 69 | print('Push UI/indexing scripts') 70 | run('scp %s -r ../gitHistory.py ../handle.py ../indexJira.py ../Latin-dont-break-issues.rbbi ../server.py ../moreFacets.py ../search.py ../static ../production ../suggest.py ../util.py %s:src/jira-ui' % (sshIdent, userHost)) 71 | 72 | if doReindex: 73 | extra = ' -reindex' 74 | else: 75 | extra = '' 76 | 77 | if doServer: 78 | extra += ' -server' 79 | 80 | print(f'\nnow restart: {extra}') 81 | run('ssh -t %s %s "cd src/jira-ui/production; python3 -u restart.py%s"' % (sshIdent, userHost, extra)) 82 | 83 | print() 84 | print('Verify') 85 | while True: 86 | try: 87 | s = urllib.request.urlopen('http://jirasearch.mikemccandless.com/search.py').read().decode('utf-8') 88 | except: 89 | print() 90 | print('Failed to load search.py... will retry:') 91 | traceback.print_exc() 92 | else: 93 | if s.find('Updated') != -1: 94 | print(' success!') 95 | break 96 | elif s.find('isn\'t started: cannot search'): 97 | time.sleep(0.5) 98 | else: 99 | print('GOT %s' % s) 100 | raise RuntimeError('server is not working?') 101 | -------------------------------------------------------------------------------- /examples/jirasearch/production/restart.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import time 17 | import urllib.request, urllib.error, urllib.parse 18 | import os 19 | import sys 20 | import shutil 21 | import signal 22 | 23 | sys.path.insert(0, '..') 24 | import localconstants 25 | 26 | PORT = localconstants.SERVER_PORT 27 | 28 | """ 29 | Production script to restart Lucene server and the UI. 30 | """ 31 | 32 | doReindex = '-reindex' in sys.argv 33 | doServer = '-server' in sys.argv 34 | 35 | def run(cmd): 36 | if os.system(cmd): 37 | raise RuntimeError('%s failed' % cmd) 38 | 39 | if doServer: 40 | print() 41 | print('Kill current runServer process') 42 | 43 | # kill runServer wrapper: 44 | found = False 45 | for line in os.popen('ps auxww | grep runServer.py | grep -v grep | grep -v /bin/sh').readlines(): 46 | pid = line.strip().split()[1] 47 | print(' kill server pid %s: %s' % (pid, line.strip())) 48 | if found: 49 | raise RuntimeError('found two pids!') 50 | try: 51 | run('kill -9 %d' % int(pid)) 52 | except: 53 | print('FAILED:') 54 | traceback.print_exc() 55 | found = True 56 | 57 | if False and not found: 58 | raise RuntimeError('could not find existing runServer.py process') 59 | 60 | print() 61 | print('Kill current java server process') 62 | 63 | # kill java process 64 | found = False 65 | for line in os.popen('ps auxww | grep java | grep server.Server | grep "ipPort localhost:%s" | grep -v grep | grep -v /bin/sh' % PORT).readlines(): 66 | pid = line.strip().split()[1] 67 | print(' kill server pid %s: %s' % (pid, line.strip())) 68 | if found: 69 | raise RuntimeError('found two pids!') 70 | try: 71 | run('kill -9 %d' % int(pid)) 72 | except: 73 | print('FAILED:') 74 | traceback.print_exc() 75 | found = True 76 | 77 | if False and not found: 78 | raise RuntimeError('could not find existing java server.Server process') 79 | 80 | print() 81 | print('Start new java server process') 82 | 83 | run('nohup python3 -u runServer.py > %s/luceneserver.log 2>&1 &' % localconstants.LOG_DIR) 84 | 85 | # Wait until server is really ready: 86 | while True: 87 | s = open('%s/luceneserver.log' % localconstants.LOG_DIR, 'rb').read() 88 | if s.find(('listening on').encode('utf-8')) != -1: 89 | break 90 | time.sleep(1.0) 91 | 92 | print() 93 | print('Restart Apache httpd') 94 | 95 | run('sudo apachectl restart') 96 | #run('sudo /etc/rc.d/init.d/httpd restart') 97 | 98 | print() 99 | print('Kill current Indexer') 100 | for line in os.popen('ps auxww | grep python | grep indexJira.py | grep -v grep | grep -v ssh').readlines(): 101 | pid = line.strip().split()[1] 102 | print(' kill indexJira process pid %s [%s]' % (pid, line)) 103 | try: 104 | run('kill -9 %d' % int(pid)) 105 | except: 106 | pass 107 | 108 | if doReindex: 109 | extra = ' -reindex -delete' 110 | else: 111 | extra = '' 112 | 113 | print() 114 | print('Start new Indexer') 115 | os.chdir('..') 116 | run('nohup python3 -u indexJira.py -server localhost:%s -nrt%s > %s/nrt.log 2>&1 &' % (PORT, extra, localconstants.LOG_DIR)) 117 | 118 | print() 119 | print('Wait 5 seconds') 120 | time.sleep(5.0) 121 | -------------------------------------------------------------------------------- /examples/jirasearch/production/restartForever.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import datetime 4 | 5 | while True: 6 | try: 7 | mb = float(os.popen('ps axuww | grep org.apache.lucene.server.Server | grep -v grep').read().split()[5])/1024. 8 | except IndexError: 9 | print('FAILED to find server process; retry in 10s') 10 | time.sleep(10.0) 11 | continue 12 | 13 | if mb > 375.0: 14 | print('%s: now restart @ %.1f MB' % (datetime.datetime.now(), mb)) 15 | os.system('python3 -u restart.py') 16 | 17 | time.sleep(10.0) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/jirasearch/production/runServer.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import threading 17 | import os 18 | import time 19 | import shutil 20 | import subprocess 21 | import sys 22 | import datetime 23 | import signal 24 | 25 | sys.path.insert(0, '..') 26 | 27 | import localconstants 28 | 29 | """ 30 | Python wrapper that spawns the Java lucene server process and restarts it if it dies. 31 | """ 32 | 33 | LUCENE_SERVER_VERSION = localconstants.LUCENE_SERVER_VERSION 34 | 35 | def readServerOutput(p, port, startupEvent, failureEvent, eachLine): 36 | while True: 37 | l = p.stdout.readline().decode('utf-8') 38 | if l == '': 39 | if not startupEvent.isSet(): 40 | failureEvent.set() 41 | startupEvent.set() 42 | raise RuntimeError('Server failed to start') 43 | else: 44 | break 45 | if 'listening on' in l: 46 | startupEvent.set() 47 | if eachLine is None: 48 | print('SVR: %s' % l.rstrip()) 49 | else: 50 | eachLine(l.rstrip()) 51 | 52 | class RunServer: 53 | 54 | """ 55 | Spawns java subprocess to run the Lucene server. 56 | """ 57 | 58 | def __init__(self, port, path, eachLine=None): 59 | self.port = port 60 | startupEvent = threading.Event() 61 | failureEvent = threading.Event() 62 | 63 | #VERSION = '4.2.0-ALPHA' 64 | #VERSION = '4.2-SNAPSHOT' 65 | 66 | HEAP = localconstants.HEAP 67 | 68 | # -agentlib:yjpagent=sampling,disablej2ee 69 | cmd = '%s -Xms%s -Xmx%s -Xss228k -cp "../luceneserver/lib/*" org.apache.lucene.server.Server -maxHTTPThreadCount 2 -ipPort localhost:%s -stateDir %s' % (localconstants.JAVA_EXE, HEAP, HEAP, port, localconstants.ROOT_INDICES_PATH) 70 | 71 | print('SERVER CMD: %s' % cmd) 72 | 73 | self.p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 74 | 75 | t = threading.Thread(target=readServerOutput, args=(self.p, port, startupEvent, failureEvent, eachLine)) 76 | t.setDaemon(True) 77 | t.start() 78 | 79 | startupEvent.wait() 80 | if failureEvent.isSet(): 81 | sys.exit(0) 82 | 83 | def isAlive(self): 84 | return self.p.poll() is None 85 | 86 | def killServer(self): 87 | try: 88 | self.send('shutdown', {}) 89 | except: 90 | pass 91 | print('Find server pid to kill...') 92 | for line in os.popen('ps auxww | grep java | grep server.Server | grep "port %s" | grep -v grep' % self.port).readlines(): 93 | pid = line.strip().split()[1] 94 | print('Kill server pid %s' % pid) 95 | try: 96 | os.kill(int(pid), signal.SIGKILL) 97 | except: 98 | pass 99 | 100 | if __name__ == '__main__': 101 | 102 | while True: 103 | print() 104 | print('%s: START SERVER' % datetime.datetime.now()) 105 | svr = RunServer(localconstants.SERVER_PORT, localconstants.ROOT_INDICES_PATH) 106 | 107 | try: 108 | while True: 109 | time.sleep(.2) 110 | if not svr.isAlive(): 111 | print('NOT ALIVE') 112 | break 113 | finally: 114 | svr.killServer() 115 | 116 | time.sleep(1) 117 | 118 | -------------------------------------------------------------------------------- /examples/jirasearch/production/snapshot.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import os 17 | import datetime 18 | 19 | """ 20 | This runs on the production box and makes a full backup of src/jira-ui in case we need to rollback. 21 | """ 22 | 23 | def run(cmd): 24 | if os.system(cmd): 25 | raise RuntimeError('%s failed' % cmd) 26 | 27 | # Take snapshot in case we need to fallback: 28 | os.chdir('../..') 29 | dt = datetime.datetime.now().date() 30 | upto = 0 31 | while True: 32 | if upto == 0: 33 | fileName = '../snapshots/jira-ui.%04d%02d%02d.tar.bz2' % (dt.year, dt.month, dt.day) 34 | else: 35 | fileName = '../snapshots/jira-ui.%04d%02d%02d-%d.tar.bz2' % (dt.year, dt.month, dt.day, upto) 36 | if not os.path.exists(fileName): 37 | print('snapshot to %s cwd=%s' % (fileName, os.getcwd())) 38 | run('tar cjf %s jira-ui' % fileName) 39 | break 40 | upto += 1 41 | 42 | -------------------------------------------------------------------------------- /examples/jirasearch/search.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import io 17 | import gzip 18 | import traceback 19 | #import sys 20 | #sys.path.insert(0, '/home/ec2-user/src/ui') 21 | import util 22 | import handle 23 | 24 | # Entry point in production: 25 | def application(environ, startResponse): 26 | return util.handleOnePage(environ, startResponse, handle.handleQuery) 27 | -------------------------------------------------------------------------------- /examples/jirasearch/static/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 |
22 |
23 |
24 |   This site uses Apache Lucene, specifically this thin-wrapper HTTP server over Lucene, to search all Solr, Tika and Infra Jira issues. See 25 | the Eating 26 | dog food with Lucene blog post and Jirasearch 2.0 dog food for details. The source code for indexing and searching Jira issues is here. 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/jirasearch/static/bootstrap/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/bootstrap/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /examples/jirasearch/static/bootstrap/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/bootstrap/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/autocomplete.css: -------------------------------------------------------------------------------- 1 | #formWrap { 2 | padding:10px; position:absolute; float:left; background-color:#000; 3 | background:rgba(0,0,0,.5); -moz-border-radius:10px; 4 | -webkit-border-radius:10px; border-radius:10px; 5 | } 6 | #messageForm { 7 | width:326px; border:1px solid #666; background-color:#eee; 8 | } 9 | #messageForm fieldset { 10 | padding:0; margin:0; position:relative; border:none; 11 | background-color:#eee; 12 | } 13 | #messageForm legend { visibility:hidden; height:0; } 14 | #messageForm span { 15 | display:block; width:326px; padding:10px 0; margin:0 0 20px; 16 | text-indent:20px; background-color:#bbb; 17 | border-bottom:1px solid #333; font:18px Georgia, Serif; color:#fff; 18 | } 19 | #friends { 20 | width:274px; padding:3px 3px 0; margin:0 auto; 21 | border:1px solid #aaa; background-color:#fff; cursor:text; 22 | } 23 | #messageForm #to { 24 | width:30px; margin:0 0 2px 0; padding:0 0 3px; 25 | position:relative; top:0; float:left; border:none; 26 | } 27 | #messageForm input, #messageForm textarea { 28 | display:block; width:274px; padding:3px; margin:0 auto 20px; 29 | border:1px solid #aaa; 30 | } 31 | #messageForm label { 32 | display:block; margin:20px 0 3px; text-indent:22px; 33 | font:bold 11px Verdana, Sans-serif; color:#666; 34 | } 35 | #messageForm #toLabel { margin-top:0; } 36 | #messageForm button { float:right; margin:0 0 20px 0; } 37 | #messageForm #cancel { margin-right:20px; } 38 | #friends span { 39 | display:block; margin:0 3px 3px 0; padding:3px 20px 4px 8px; 40 | position:relative; float:left; background-color:#eee; 41 | border:1px solid #333; -moz-border-radius:7px; 42 | -webkit-border-radius:7px; border-radius:7px; color:#333; 43 | font:normal 11px Verdana, Sans-serif; 44 | } 45 | #friends span a { 46 | position:absolute; right:8px; top:2px; color:#666; 47 | font:bold 12px Verdana, Sans-serif; text-decoration:none; 48 | } 49 | #friends span a:hover { color:#ff0000; } 50 | .ui-menu .ui-menu-item { white-space:nowrap; padding:0 10px 0 0; } 51 | -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/animated-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/animated-overlay.gif -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-icons_228ef1_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-icons_228ef1_256x240.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-icons_ef8c08_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-icons_ef8c08_256x240.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-icons_ffd27a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-icons_ffd27a_256x240.png -------------------------------------------------------------------------------- /examples/jirasearch/static/css/ui-lightness/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/css/ui-lightness/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /examples/jirasearch/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/favicon.ico -------------------------------------------------------------------------------- /examples/jirasearch/static/img/1star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/img/1star.gif -------------------------------------------------------------------------------- /examples/jirasearch/static/img/2star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/img/2star.gif -------------------------------------------------------------------------------- /examples/jirasearch/static/img/3star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/img/3star.gif -------------------------------------------------------------------------------- /examples/jirasearch/static/img/4star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/img/4star.gif -------------------------------------------------------------------------------- /examples/jirasearch/static/img/5star.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/img/5star.gif -------------------------------------------------------------------------------- /examples/jirasearch/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /search.py 3 | Disallow: /moreFacets.py 4 | Disallow: /suggest.py 5 | -------------------------------------------------------------------------------- /examples/jirasearch/static/select2/select2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/select2/select2.png -------------------------------------------------------------------------------- /examples/jirasearch/static/select2/select2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/select2/select2x2.png -------------------------------------------------------------------------------- /examples/jirasearch/static/select2/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemccand/luceneserver/e573ed76f6579824d18bcba7e245e6d860947d0f/examples/jirasearch/static/select2/spinner.gif -------------------------------------------------------------------------------- /examples/jirasearch/suggest.py: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | #import sys 17 | #sys.path.insert(0, '/home/changingbits/src/ui') 18 | import util 19 | import handle 20 | 21 | # Entry point in production: 22 | def application(environ, startResponse): 23 | return util.handleOnePage(environ, startResponse, handle.handleSuggest) 24 | -------------------------------------------------------------------------------- /scripts/esJSONToLuceneServerJSON.py: -------------------------------------------------------------------------------- 1 | import struct 2 | import json 3 | import sys 4 | 5 | class BlockedFileReader: 6 | 7 | def __init__(self, fileName): 8 | self.f = open(fileName, 'rb') 9 | self.pending = self.read() 10 | self.pendingUpto = 0 11 | 12 | def __enter__(self): 13 | return self 14 | 15 | def __exit__(self, exc_type, exc_value, traceback): 16 | self.f.close() 17 | 18 | def read(self): 19 | b = self.f.read(8) 20 | if len(b) == 0: 21 | return None 22 | count, length = struct.unpack('ii', b) 23 | data = self.f.read(length) 24 | return data 25 | 26 | def readline(self): 27 | while True: 28 | i = self.pending.find(b'\n', self.pendingUpto) 29 | if i == -1: 30 | self.pending = self.pending[self.pendingUpto:] 31 | self.pendingUpto = 0 32 | inc = self.read() 33 | if inc is None: 34 | if len(self.pending) > 0: 35 | result = self.pending 36 | self.pending = b'' 37 | return result 38 | else: 39 | return None 40 | else: 41 | self.pending += inc 42 | else: 43 | result = self.pending[self.pendingUpto:i+1] 44 | self.pendingUpto = i+1 45 | return result 46 | 47 | class BlockedFileWriter: 48 | 49 | def __init__(self, fileName, minBlockBytes): 50 | self.f = open(fileName, 'wb') 51 | self.minBlockBytes = minBlockBytes 52 | self.pending = [] 53 | self.pendingLength = 0 54 | 55 | def __enter__(self): 56 | return self 57 | 58 | def __exit__(self, exc_type, exc_value, traceback): 59 | self.f.close() 60 | 61 | def add(self, b): 62 | if b'\n' in b: 63 | raise RuntimeError('entry cannot contain newline') 64 | self.pending.append(b) 65 | self.pendingLength += len(b)+1 66 | if self.pendingLength > self.minBlockBytes: 67 | self.flush() 68 | 69 | def flush(self): 70 | self.f.write(struct.pack('ii', len(self.pending), self.pendingLength)) 71 | self.f.write(b'\n'.join(self.pending) + b'\n') 72 | self.pending = [] 73 | self.pendingLength = 0 74 | 75 | def close(self): 76 | if len(self.pending) > 0: 77 | self.flush() 78 | self.f.close() 79 | 80 | srcFile, destFile = sys.argv[1:3] 81 | 82 | with BlockedFileReader(srcFile) as fIn, BlockedFileWriter(destFile, 1024*1024) as fOut: 83 | while True: 84 | if fIn.readline() is None: 85 | break 86 | s = fIn.readline() 87 | #print("add %s" % s) 88 | fOut.add(s[:-1]) 89 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/Connection.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.BufferedOutputStream; 21 | import java.io.Closeable; 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.net.InetSocketAddress; 25 | import java.net.Socket; 26 | 27 | import org.apache.lucene.store.DataInput; 28 | import org.apache.lucene.store.DataOutput; 29 | import org.apache.lucene.store.InputStreamDataInput; 30 | import org.apache.lucene.store.OutputStreamDataOutput; 31 | 32 | /** Simple point-to-point TCP connection */ 33 | public class Connection implements Closeable { 34 | public final DataInput in; 35 | public final DataOutput out; 36 | public final InputStream sockIn; 37 | public final BufferedOutputStream bos; 38 | public final Socket s; 39 | public final InetSocketAddress destAddress; 40 | public long lastKeepAliveNS = System.nanoTime(); 41 | 42 | public Connection(InetSocketAddress address) throws IOException { 43 | this.destAddress = address; 44 | System.out.println("CONNECT: " + address); 45 | this.s = new Socket(address.getAddress(), address.getPort()); 46 | this.sockIn = s.getInputStream(); 47 | this.in = new InputStreamDataInput(sockIn); 48 | // nocommit don't use BOS (it's trappy: you can forget to flush); do our own buffering above so the protocol is explicit: 49 | this.bos = new BufferedOutputStream(s.getOutputStream()); 50 | this.out = new OutputStreamDataOutput(bos); 51 | } 52 | 53 | public void flush() throws IOException { 54 | bos.flush(); 55 | } 56 | 57 | @Override 58 | public void close() throws IOException { 59 | s.close(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/Constants.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.regex.Pattern; 21 | 22 | /** Static constants. */ 23 | public class Constants { 24 | private Constants() { 25 | } 26 | 27 | // nocommit can we nuke this hack now? 28 | /** Used to join multi-valued fields. */ 29 | public static final char INFORMATION_SEP = '\u001f'; 30 | 31 | /** Regexp version of {@link #INFORMATION_SEP}. */ 32 | public static final String INFORMATION_SEP_REGEX = Pattern.quote(Character.toString(INFORMATION_SEP)); 33 | } 34 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/DirectoryFactory.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /** 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.lang.reflect.Constructor; 22 | import java.lang.reflect.InvocationTargetException; 23 | import java.nio.file.Path; 24 | 25 | //import org.apache.lucene.store.AsyncFSDirectory; 26 | import org.apache.lucene.store.Directory; 27 | import org.apache.lucene.store.FSDirectory; 28 | import org.apache.lucene.store.MMapDirectory; 29 | import org.apache.lucene.store.NIOFSDirectory; 30 | 31 | /** A factory to open a {@link Directory} from a provided 32 | * filesystem path. */ 33 | public abstract class DirectoryFactory { 34 | 35 | /** Sole constructor. */ 36 | public DirectoryFactory() { 37 | } 38 | 39 | /** Open a new {@link Directory} at the specified path. */ 40 | public abstract Directory open(Path path) throws IOException; 41 | 42 | /** Returns an instance, using the specified 43 | * implementation {FSDirectory, MMapDirectory, 44 | * NIOFSDirectory}. */ 45 | public static DirectoryFactory get(final String dirImpl) { 46 | if (dirImpl.equals("FSDirectory")) { 47 | return new DirectoryFactory() { 48 | @Override 49 | public Directory open(Path path) throws IOException { 50 | return FSDirectory.open(path); 51 | } 52 | }; 53 | } else if (dirImpl.equals("MMapDirectory")) { 54 | return new DirectoryFactory() { 55 | @Override 56 | public Directory open(Path path) throws IOException { 57 | return new MMapDirectory(path); 58 | } 59 | }; 60 | } else if (dirImpl.equals("NIOFSDirectory")) { 61 | return new DirectoryFactory() { 62 | @Override 63 | public Directory open(Path path) throws IOException { 64 | return new NIOFSDirectory(path); 65 | } 66 | }; 67 | } else { 68 | final Class dirClass; 69 | try { 70 | dirClass = Class.forName(dirImpl).asSubclass(Directory.class); 71 | } catch (ClassNotFoundException cnfe) { 72 | throw new IllegalArgumentException("could not locate Directory sub-class \"" + dirImpl + "\"; verify CLASSPATH"); 73 | } 74 | final Constructor ctor; 75 | try { 76 | ctor = dirClass.getConstructor(Path.class); 77 | } catch (NoSuchMethodException nsme) { 78 | throw new IllegalArgumentException("class \"" + dirImpl + "\" does not have a constructor taking a single Path argument"); 79 | } 80 | 81 | return new DirectoryFactory() { 82 | @Override 83 | public Directory open(Path path) throws IOException { 84 | try { 85 | return ctor.newInstance(path); 86 | } catch (InstantiationException ie) { 87 | throw new RuntimeException("failed to instantiate directory class \"" + dirImpl + "\" on path=\"" + path + "\"", ie); 88 | } catch (InvocationTargetException ite) { 89 | throw new RuntimeException("failed to instantiate directory class \"" + dirImpl + "\" on path=\"" + path + "\"", ite); 90 | } catch (IllegalAccessException iae) { 91 | throw new RuntimeException("failed to instantiate directory class \"" + dirImpl + "\" on path=\"" + path + "\"", iae); 92 | } 93 | } 94 | }; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/FieldDefBindings.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.Map; 21 | 22 | import org.apache.lucene.expressions.Bindings; 23 | import org.apache.lucene.index.DocValuesType; 24 | import org.apache.lucene.search.DoubleValuesSource; 25 | 26 | /** Implements {@link Bindings} on top of the registered 27 | * fields. */ 28 | public final class FieldDefBindings extends Bindings { 29 | 30 | private final Map fields; 31 | 32 | /** Sole constructor. */ 33 | public FieldDefBindings(Map fields) { 34 | this.fields = fields; 35 | } 36 | 37 | @Override 38 | public DoubleValuesSource getDoubleValuesSource(String name) { 39 | if (name.equals("_score")) { 40 | return DoubleValuesSource.SCORES; 41 | } 42 | FieldDef fd = fields.get(name); 43 | if (fd == null) { 44 | throw new IllegalArgumentException("Invalid reference '" + name + "'"); 45 | } 46 | if (fd.valueType == FieldDef.FieldValueType.VIRTUAL) { 47 | return fd.valueSource; 48 | } else if (fd.fieldType != null && fd.fieldType.docValuesType() == DocValuesType.NUMERIC) { 49 | if (fd.valueType == FieldDef.FieldValueType.INT) { 50 | return DoubleValuesSource.fromIntField(name); 51 | } else if (fd.valueType == FieldDef.FieldValueType.FLOAT) { 52 | return DoubleValuesSource.fromFloatField(name); 53 | } else if (fd.valueType == FieldDef.FieldValueType.LONG) { 54 | return DoubleValuesSource.fromLongField(name); 55 | } else if (fd.valueType == FieldDef.FieldValueType.DOUBLE) { 56 | return DoubleValuesSource.fromDoubleField(name); 57 | } else { 58 | assert false: "unknown numeric field type: " + fd.valueType; 59 | return null; 60 | } 61 | } else { 62 | throw new IllegalArgumentException("Field \'" + name + "\' cannot be used in an expression: it was not registered with sort=true"); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/FinishRequest.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | // nocommit: javadocs seem outdated 21 | 22 | /** Returned from {@code Handler#finish} to make actual 23 | * changes from the request. We do this two-step 24 | * process so that we can fail if there are unhandled 25 | * params, without having made any changes to the index. */ 26 | public interface FinishRequest { 27 | 28 | /** Perform the actual work of the request. */ 29 | public String finish() throws Exception; 30 | } 31 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/MyIndexSearcher.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.List; 22 | 23 | import org.apache.lucene.index.IndexReader; 24 | import org.apache.lucene.index.LeafReaderContext; 25 | import org.apache.lucene.search.BulkScorer; 26 | import org.apache.lucene.search.CollectionTerminatedException; 27 | import org.apache.lucene.search.Collector; 28 | import org.apache.lucene.search.DocIdSetIterator; 29 | import org.apache.lucene.search.IndexSearcher; 30 | import org.apache.lucene.search.LeafCollector; 31 | import org.apache.lucene.search.Query; 32 | import org.apache.lucene.search.Scorer; 33 | import org.apache.lucene.search.Weight; 34 | import org.apache.lucene.search.join.ToParentBlockJoinQuery; 35 | import org.apache.lucene.util.Bits; 36 | 37 | /** This is sadly necessary because for ToParentBlockJoinQuery we must invoke .scorer not .bulkScorer, yet for DrillSideways we must do 38 | * exactly the opposite! */ 39 | 40 | public class MyIndexSearcher extends IndexSearcher { 41 | public MyIndexSearcher(IndexReader reader) { 42 | super(reader); 43 | } 44 | 45 | @Override 46 | protected void search(List leaves, Weight weight, Collector collector) throws IOException { 47 | 48 | // nocommit -- removeme? do we still rely on this Scorer not BulkScorer / getChildren? 49 | for (LeafReaderContext ctx : leaves) { // search each subreader 50 | // we force the use of Scorer (not BulkScorer) to make sure 51 | // that the scorer passed to LeafCollector.setScorer supports 52 | // Scorer.getChildren -- messy messy! maybe broken now? 53 | final LeafCollector leafCollector = collector.getLeafCollector(ctx); 54 | if (weight.getQuery().toString().contains("DrillSidewaysQuery")) { 55 | BulkScorer scorer = weight.bulkScorer(ctx); 56 | if (scorer != null) { 57 | try { 58 | scorer.score(leafCollector, ctx.reader().getLiveDocs()); 59 | } catch (CollectionTerminatedException e) { 60 | // collection was terminated prematurely 61 | // continue with the following leaf 62 | } 63 | } 64 | } else { 65 | Scorer scorer = weight.scorer(ctx); 66 | if (scorer != null) { 67 | leafCollector.setScorer(scorer); 68 | final Bits liveDocs = ctx.reader().getLiveDocs(); 69 | final DocIdSetIterator it = scorer.iterator(); 70 | for (int doc = it.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; doc = it.nextDoc()) { 71 | if (liveDocs == null || liveDocs.get(doc)) { 72 | leafCollector.collect(doc); 73 | } 74 | } 75 | } 76 | } 77 | 78 | // Note: this is called if collection ran successfully, including the above special cases of 79 | // CollectionTerminatedException and TimeExceededException, but no other exception. 80 | leafCollector.finish(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/PreHandle.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.apache.lucene.server.params.Request; 21 | 22 | // nocommit: outdated javadocs? 23 | 24 | /** A callback that can modify a request before the main 25 | * {@code Handler} sees it. Plugins can use this to 26 | * pre-process requests. */ 27 | 28 | public interface PreHandle { 29 | 30 | /** Invoked before the selected handler runs. */ 31 | public void invoke(Request request) throws Exception; 32 | } 33 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/QueryID.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.Arrays; 21 | 22 | import org.apache.lucene.util.StringHelper; 23 | 24 | /** Uniquely identifies a query; just a thin wrapper around a byte[] so we can define equals/hashCode. */ 25 | 26 | public class QueryID { 27 | 28 | public final byte[] id; 29 | 30 | public QueryID() { 31 | this(StringHelper.randomId()); 32 | } 33 | 34 | public QueryID(byte[] id) { 35 | this.id = id; 36 | } 37 | 38 | @Override 39 | public boolean equals(Object other) { 40 | if (other instanceof QueryID) { 41 | return Arrays.equals(((QueryID) other).id, id); 42 | } else { 43 | return false; 44 | } 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return Arrays.hashCode(id); 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return StringHelper.idToString(id); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/RemoteNodeConnection.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.Closeable; 21 | import java.io.IOException; 22 | 23 | /** Persistent connections to other nodes in the cluster for us to send commands to them */ 24 | public final class RemoteNodeConnection implements Closeable { 25 | public final byte[] nodeID; 26 | public final Connection c; 27 | 28 | public RemoteNodeConnection(byte[] nodeID, Connection c) { 29 | this.nodeID = nodeID; 30 | this.c = c; 31 | } 32 | 33 | @Override 34 | public void close() throws IOException { 35 | c.close(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/ServerCodec.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.apache.lucene.codecs.Codec; 21 | import org.apache.lucene.codecs.DocValuesFormat; 22 | import org.apache.lucene.codecs.PostingsFormat; 23 | import org.apache.lucene.codecs.lucene95.Lucene95Codec; 24 | 25 | /** Implements per-index {@link Codec}. */ 26 | 27 | public class ServerCodec extends Lucene95Codec { 28 | 29 | public final static String DEFAULT_POSTINGS_FORMAT = "Lucene90"; 30 | public final static String DEFAULT_DOC_VALUES_FORMAT = "Lucene90"; 31 | 32 | private final IndexState state; 33 | // nocommit expose compression control 34 | 35 | /** Sole constructor. */ 36 | public ServerCodec(IndexState state) { 37 | this.state = state; 38 | } 39 | 40 | @Override 41 | public PostingsFormat getPostingsFormatForField(String field) { 42 | String pf; 43 | try { 44 | pf = state.getField(field).postingsFormat; 45 | } catch (IllegalArgumentException iae) { 46 | // The indexed facets field will have drill-downs, 47 | // which will pull the postings format: 48 | if (state.internalFacetFieldNames.contains(field)) { 49 | return super.getPostingsFormatForField(field); 50 | } else { 51 | throw iae; 52 | } 53 | } 54 | return PostingsFormat.forName(pf); 55 | } 56 | 57 | @Override 58 | public DocValuesFormat getDocValuesFormatForField(String field) { 59 | String dvf; 60 | try { 61 | dvf = state.getField(field).docValuesFormat; 62 | } catch (IllegalArgumentException iae) { 63 | if (state.internalFacetFieldNames.contains(field)) { 64 | return super.getDocValuesFormatForField(field); 65 | } else { 66 | throw iae; 67 | } 68 | } 69 | return DocValuesFormat.forName(dvf); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/WholeMVJSONPassageFormatter.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.apache.lucene.search.uhighlight.Passage; 21 | import org.apache.lucene.search.uhighlight.PassageFormatter; 22 | import net.minidev.json.JSONArray; 23 | import net.minidev.json.JSONObject; 24 | 25 | /** From a multi-valued field (indexed with the values 26 | * joined with INFO_SEP), highlight each value entirely. */ 27 | public class WholeMVJSONPassageFormatter extends PassageFormatter { 28 | 29 | private final int offsetGap; 30 | 31 | /** Create this, with the specified offsetGap. */ 32 | public WholeMVJSONPassageFormatter(int offsetGap) { 33 | this.offsetGap = offsetGap; 34 | } 35 | 36 | /** Carefully finds the field boundaries 37 | * (INFORMATION_SEPARATOR) in the content and builds a 38 | * JSONArray so that each original field value is 39 | * separated and highlighted. */ 40 | @Override 41 | public JSONArray format(Passage[] passages, String content) { 42 | 43 | // Caller must use WholeBreakIterator: 44 | assert passages.length == 1; 45 | Passage passage = passages[0]; 46 | 47 | String[] chunks = content.split(Constants.INFORMATION_SEP_REGEX); 48 | JSONArray result = new JSONArray(); 49 | int matchUpto = 0; 50 | int charOffset = 0; 51 | for(String chunk : chunks) { 52 | JSONArray part = new JSONArray(); 53 | result.add(part); 54 | int pos = 0; 55 | int posEnd = chunk.length(); 56 | while (matchUpto < passage.getNumMatches()) { 57 | int start = passage.getMatchStarts()[matchUpto] - charOffset; 58 | if (start >= posEnd) { 59 | break; 60 | } 61 | if (start > pos) { 62 | part.add(chunk.substring(pos, start)); 63 | pos = start; 64 | } 65 | JSONObject match = new JSONObject(); 66 | part.add(match); 67 | int end = passage.getMatchEnds()[matchUpto] - charOffset; 68 | match.put("text", chunk.substring(start, end)); 69 | match.put("term", passage.getMatchTerms()[matchUpto].utf8ToString()); 70 | pos = end; 71 | matchUpto++; 72 | } 73 | if (pos < chunk.length()) { 74 | part.add(chunk.substring(pos)); 75 | pos = chunk.length(); 76 | } 77 | 78 | // nocommit we always join w/ INFO_SEP ... so it 79 | //should just be 1? 80 | //charOffset += chunk.length()+offsetGap; 81 | charOffset += chunk.length()+1; 82 | } 83 | 84 | return result; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/AddDocumentsHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.StringReader; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.server.FinishRequest; 25 | import org.apache.lucene.server.GlobalState; 26 | import org.apache.lucene.server.IndexState; 27 | import org.apache.lucene.server.params.*; 28 | import net.minidev.json.JSONArray; 29 | import net.minidev.json.JSONObject; 30 | import net.minidev.json.JSONValue; 31 | 32 | /** Handles {@code addDocuments}, by delegating the single 33 | * document to {@link BulkAddDocumentsHandler} */ 34 | public class AddDocumentsHandler extends Handler { 35 | 36 | final static StructType TYPE = new StructType( 37 | new Param("indexName", "Index name", new StringType()), 38 | new Param("parent", "The (one) parent document for this block. The value of this key is a single document that @addDocument expects. Be sure to add an indexed field to only the parent document so that you can subsequently provide the filter that identifies only parent documents.", 39 | AddDocumentHandler.DOCUMENT_TYPE), 40 | new Param("children", "List of child documents.", 41 | new ListType(AddDocumentHandler.DOCUMENT_TYPE))); 42 | 43 | @Override 44 | public StructType getType() { 45 | return TYPE; 46 | } 47 | 48 | @Override 49 | public String getTopDoc() { 50 | return "Adds one document block (= single parent and multiple children) to the index. This can be used for block grouping and block joins. Returns the index generation (indexGen) that contains this added document block."; 51 | } 52 | 53 | /** Sole constructor. */ 54 | public AddDocumentsHandler(GlobalState state) { 55 | super(state); 56 | } 57 | 58 | @Override 59 | public FinishRequest handle(final IndexState state, final Request r, Map> params) throws Exception { 60 | 61 | state.verifyStarted(r); 62 | 63 | // NOTE: somewhat wasteful since we re-serialize to 64 | // string only to re-parse the JSON, but this allows 65 | // single-source (bulk) for parsing, and apps that care 66 | // about performance will use bulk APIs: 67 | 68 | JSONObject raw = r.getRawParams(); 69 | StringBuilder sb = new StringBuilder(); 70 | sb.append("{\"indexName\": \""); 71 | sb.append(state.name); 72 | sb.append("\", \"documents\": ["); 73 | sb.append(raw.toString()); 74 | sb.append("]}"); 75 | raw.clear(); 76 | 77 | final String bulkRequestString = sb.toString(); 78 | 79 | return new FinishRequest() { 80 | @Override 81 | public String finish() throws Exception { 82 | String result = globalState.getHandler("bulkAddDocuments").handleStreamed(new StringReader(bulkRequestString), null); 83 | if (result.indexOf("errors") != -1) { 84 | JSONObject o = (JSONObject) JSONValue.parseStrict(result); 85 | if (o.containsKey("errors")) { 86 | JSONObject err = (JSONObject) ((JSONArray) o.get("errors")).get(0); 87 | throw new IllegalArgumentException((String) err.get("exception")); 88 | } 89 | } 90 | return result; 91 | } 92 | }; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/AddReplicaHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.InputStream; 21 | import java.io.OutputStream; 22 | import java.net.InetAddress; 23 | import java.net.InetSocketAddress; 24 | import java.util.List; 25 | import java.util.Map; 26 | 27 | import org.apache.lucene.server.FinishRequest; 28 | import org.apache.lucene.server.GlobalState; 29 | import org.apache.lucene.server.IndexState; 30 | import org.apache.lucene.server.ShardState; 31 | import org.apache.lucene.server.params.Request; 32 | import org.apache.lucene.server.params.StructType; 33 | import org.apache.lucene.store.DataInput; 34 | import org.apache.lucene.store.DataOutput; 35 | 36 | /** This is invoked on the primary for an index to record that a new replica is starting */ 37 | public class AddReplicaHandler extends Handler { 38 | private static StructType TYPE = new StructType(); 39 | 40 | @Override 41 | public StructType getType() { 42 | return TYPE; 43 | } 44 | 45 | @Override 46 | public boolean binaryRequest() { 47 | return true; 48 | } 49 | 50 | @Override 51 | public void handleBinary(InputStream streamIn, DataInput in, DataOutput out, OutputStream streamOut) throws Exception { 52 | String indexName = in.readString(); 53 | IndexState indexState = globalState.getIndex(indexName); 54 | ShardState shardState = indexState.getShard(0); 55 | if (shardState.isPrimary() == false) { 56 | throw new IllegalArgumentException("index \"" + indexName + "\" was not started or is not a primary"); 57 | } 58 | 59 | int replicaID = in.readVInt(); 60 | 61 | System.out.println("AddReplicaHandler: add indexName=" + indexName); 62 | 63 | // nocommit factor this out into readInetSocketAddress: 64 | int port = in.readVInt(); 65 | int length = in.readVInt(); 66 | byte[] bytes = new byte[length]; 67 | in.readBytes(bytes, 0, length); 68 | 69 | InetSocketAddress replicaAddress = new InetSocketAddress(InetAddress.getByAddress(bytes), port); 70 | System.out.println("AddReplicaHandler: now add ID=" + replicaID + " address=" + replicaAddress); 71 | shardState.nrtPrimaryNode.addReplica(replicaID, replicaAddress); 72 | } 73 | 74 | @Override 75 | public FinishRequest handle(IndexState state, Request request, Map> params) { 76 | throw new UnsupportedOperationException(); 77 | } 78 | 79 | @Override 80 | public String getTopDoc() { 81 | return "Notifies primary that a new replica is starting"; 82 | } 83 | 84 | /** Sole constructor. */ 85 | public AddReplicaHandler(GlobalState state) { 86 | super(state); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/CannedScorer.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.apache.lucene.search.DocIdSetIterator; 21 | import org.apache.lucene.search.Scorer; 22 | import org.apache.lucene.search.Weight; 23 | 24 | // TODO: somehow share w/ the many copies of this class in 25 | // Lucene ... but I don't want to lend the thing any 26 | // credibility!! 27 | final class CannedScorer extends Scorer { 28 | 29 | final float score; 30 | final int doc; 31 | 32 | public CannedScorer(Weight weight, int doc, float score) { 33 | super(weight); 34 | this.doc = doc; 35 | this.score = score; 36 | } 37 | 38 | @Override 39 | public float score() { 40 | return score; 41 | } 42 | 43 | @Override 44 | public DocIdSetIterator iterator() { 45 | return null; 46 | } 47 | 48 | @Override 49 | public int docID() { 50 | return doc; 51 | } 52 | 53 | @Override 54 | public float getMaxScore(int upTo) { 55 | return 1f; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/CommitHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.server.FinishRequest; 25 | import org.apache.lucene.server.GlobalState; 26 | import org.apache.lucene.server.IndexState; 27 | import org.apache.lucene.server.ShardState; 28 | import org.apache.lucene.server.params.*; 29 | 30 | /** Handles {@code commit}. */ 31 | public class CommitHandler extends Handler { 32 | 33 | private static StructType TYPE = new StructType( 34 | new Param("indexName", "Index name", new StringType())); 35 | 36 | /** Sole constructor. */ 37 | public CommitHandler(GlobalState state) { 38 | super(state); 39 | } 40 | 41 | @Override 42 | public StructType getType() { 43 | return TYPE; 44 | } 45 | 46 | @Override 47 | public String getTopDoc() { 48 | return "Commits all pending changes to durable storage."; 49 | } 50 | 51 | @Override 52 | public FinishRequest handle(final IndexState indexState, Request r, Map> params) throws Exception { 53 | final ShardState shardState = indexState.getShard(0); 54 | return new FinishRequest() { 55 | @Override 56 | public String finish() throws IOException { 57 | long gen = indexState.commit(); 58 | return "{\"indexGen\": " + gen + "}"; 59 | } 60 | }; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/CreateIndexHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.nio.file.Path; 21 | import java.nio.file.Paths; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | import org.apache.lucene.server.FinishRequest; 26 | import org.apache.lucene.server.GlobalState; 27 | import org.apache.lucene.server.IndexState; 28 | import org.apache.lucene.server.params.Param; 29 | import org.apache.lucene.server.params.Request; 30 | import org.apache.lucene.server.params.StringType; 31 | import org.apache.lucene.server.params.StructType; 32 | 33 | /** Handles {@code createIndex}. */ 34 | public class CreateIndexHandler extends Handler { 35 | private static StructType TYPE = new StructType( 36 | new Param("indexName", "Index name", new StringType()), 37 | new Param("rootDir", "Filesystem path where all state is stored", new StringType())); 38 | 39 | /** Sole constructor. */ 40 | public CreateIndexHandler(GlobalState state) { 41 | super(state); 42 | requiresIndexName = false; 43 | } 44 | 45 | @Override 46 | public StructType getType() { 47 | return TYPE; 48 | } 49 | 50 | @Override 51 | public String getTopDoc() { 52 | return "Create an index"; 53 | } 54 | 55 | @Override 56 | public FinishRequest handle(final IndexState indexState, final Request r, Map> params) throws Exception { 57 | final String indexName = r.getString("indexName"); 58 | if (!IndexState.isSimpleName(indexName)) { 59 | r.fail("indexName", "invalid indexName \"" + indexName + "\": must be [a-zA-Z_][a-zA-Z0-9]*"); 60 | } 61 | final Path rootDir; 62 | if (r.hasParam("rootDir")) { 63 | rootDir = Paths.get(r.getString("rootDir")); 64 | } else { 65 | rootDir = null; 66 | } 67 | 68 | return new FinishRequest() { 69 | @Override 70 | public String finish() throws Exception { 71 | IndexState indexState; 72 | try { 73 | indexState = globalState.createIndex(indexName, rootDir); 74 | } catch (IllegalArgumentException iae) { 75 | throw r.bad("invalid indexName \"" + indexName + "\": " + iae.toString(), iae); 76 | } 77 | // Create the first shard 78 | indexState.addShard(0, true); 79 | return "{}"; 80 | } 81 | }; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/DeleteAllDocumentsHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.server.FinishRequest; 25 | import org.apache.lucene.server.GlobalState; 26 | import org.apache.lucene.server.IndexState; 27 | import org.apache.lucene.server.ShardState; 28 | import org.apache.lucene.server.params.*; 29 | import net.minidev.json.JSONObject; 30 | 31 | /** Handles {@code deleteAllDocuments}. */ 32 | public class DeleteAllDocumentsHandler extends Handler { 33 | 34 | private final static StructType TYPE = 35 | new StructType(new Param("indexName", "Which index to search", new StringType())); 36 | 37 | @Override 38 | public StructType getType() { 39 | return TYPE; 40 | } 41 | 42 | @Override 43 | public String getTopDoc() { 44 | return "Removes all documents in the index, but keeps all registered fields, settings and any built suggesters."; 45 | } 46 | 47 | /** Sole constructor. */ 48 | public DeleteAllDocumentsHandler(GlobalState state) { 49 | super(state); 50 | } 51 | 52 | @Override 53 | public FinishRequest handle(final IndexState indexState, Request r, Map> params) throws Exception { 54 | indexState.verifyStarted(r); 55 | ShardState shardState = indexState.getShard(0); 56 | return new FinishRequest() { 57 | @Override 58 | public String finish() throws IOException { 59 | // nocommit should also somehow reset taxo index? 60 | long gen = shardState.writer.deleteAll(); 61 | JSONObject r = new JSONObject(); 62 | r.put("indexGen", gen); 63 | return r.toString(); 64 | } 65 | }; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/DeleteDocumentsHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.index.Term; 25 | import org.apache.lucene.server.FinishRequest; 26 | import org.apache.lucene.server.GlobalState; 27 | import org.apache.lucene.server.IndexState; 28 | import org.apache.lucene.server.ShardState; 29 | import org.apache.lucene.server.params.ListType; 30 | import org.apache.lucene.server.params.Param; 31 | import org.apache.lucene.server.params.Request; 32 | import org.apache.lucene.server.params.StringType; 33 | import org.apache.lucene.server.params.StructType; 34 | 35 | import net.minidev.json.JSONObject; 36 | 37 | /** Handles {@code deleteDocuments}. */ 38 | public class DeleteDocumentsHandler extends Handler { 39 | // TODO: support delete by query too: 40 | // TODO: support bulk api? 41 | final static StructType TYPE = new StructType( 42 | new Param("indexName", "Index name", new StringType()), 43 | new Param("field", "Field to match to identify the deleted documents.", new StringType()), 44 | new Param("values", "Values to delete.", new ListType(new StringType()))); 45 | 46 | @Override 47 | public StructType getType() { 48 | return TYPE; 49 | } 50 | 51 | @Override 52 | public String getTopDoc() { 53 | return "Delete documents. Returns the index generation (indexGen) that reflext the deletion."; 54 | } 55 | 56 | /** Sole constructor. */ 57 | public DeleteDocumentsHandler(GlobalState state) { 58 | super(state); 59 | } 60 | 61 | @Override 62 | public FinishRequest handle(final IndexState indexState, final Request r, Map> params) throws Exception { 63 | final ShardState shardState = indexState.getShard(0); 64 | final String field = r.getString("field"); 65 | final List ids = r.getList("values"); 66 | final Term[] terms = new Term[ids.size()]; 67 | for(int i=0;i> params) throws Exception { 54 | return new FinishRequest() { 55 | @Override 56 | public String finish() throws IOException { 57 | state.close(); 58 | state.deleteIndex(); 59 | 60 | return "{}"; 61 | } 62 | }; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/HelpHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import net.minidev.json.JSONObject; 8 | import net.minidev.json.JSONStyleIdent; 9 | 10 | import org.apache.lucene.server.FinishRequest; 11 | import org.apache.lucene.server.GlobalState; 12 | import org.apache.lucene.server.IndexState; 13 | import org.apache.lucene.server.params.Param; 14 | import org.apache.lucene.server.params.Request; 15 | import org.apache.lucene.server.params.StringType; 16 | import org.apache.lucene.server.params.StructType; 17 | 18 | /* 19 | * Licensed to the Apache Software Foundation (ASF) under one or more 20 | * contributor license agreements. See the NOTICE file distributed with 21 | * this work for additional information regarding copyright ownership. 22 | * The ASF licenses this file to You under the Apache License, Version 2.0 23 | * (the "License"); you may not use this file except in compliance with 24 | * the License. You may obtain a copy of the License at 25 | * 26 | * http://www.apache.org/licenses/LICENSE-2.0 27 | * 28 | * Unless required by applicable law or agreed to in writing, software 29 | * distributed under the License is distributed on an "AS IS" BASIS, 30 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 31 | * See the License for the specific language governing permissions and 32 | * limitations under the License. 33 | */ 34 | 35 | public class HelpHandler extends Handler { 36 | 37 | /** The parameters this handler accepts. */ 38 | public final static StructType TYPE = 39 | new StructType( 40 | new Param("message", "Optional message to tell user why Help was invoked.", new StringType()) 41 | ); 42 | 43 | /** Sole constructor. */ 44 | public HelpHandler(GlobalState globalState) { 45 | super(globalState); 46 | requiresIndexName = false; 47 | } 48 | 49 | @Override 50 | public FinishRequest handle(IndexState state, Request request, 51 | Map> params) throws Exception { 52 | final JSONObject result = new JSONObject(); 53 | if(request.hasParam("message")) { 54 | result.put("message", request.getString("message")); 55 | } 56 | Map handlerInfo = new LinkedHashMap(); 57 | for(Map.Entry entry : globalState.getHandlers().entrySet()) { 58 | String handlerName = entry.getKey(); 59 | Handler handler = entry.getValue(); 60 | String handlerDesc = handler.getTopDoc(); 61 | Map paramInfo = new LinkedHashMap(); 62 | for(Map.Entry paramEntry : handler.getType().params.entrySet()) { 63 | Param param = paramEntry.getValue(); 64 | paramInfo.put(paramEntry.getKey(), param.desc + " (" + param.type.getClass().getSimpleName() + ")"); 65 | } 66 | JSONObject handlerJson = new JSONObject(); 67 | handlerJson.put("description", handlerDesc); 68 | handlerJson.put("parameters", paramInfo); 69 | handlerInfo.put(handlerName, handlerJson); 70 | } 71 | result.put("Available Handlers", handlerInfo); 72 | 73 | return new FinishRequest() { 74 | @Override 75 | public String finish() { 76 | return result.toString(new JSONStyleIdent()); 77 | } 78 | }; 79 | } 80 | 81 | @Override 82 | public StructType getType() { 83 | return TYPE; 84 | } 85 | 86 | @Override 87 | public String getTopDoc() { 88 | return "Display help on server usage."; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/IndexStatusHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | import org.apache.lucene.server.FinishRequest; 24 | import org.apache.lucene.server.GlobalState; 25 | import org.apache.lucene.server.IndexState; 26 | import org.apache.lucene.server.params.Param; 27 | import org.apache.lucene.server.params.Request; 28 | import org.apache.lucene.server.params.StringType; 29 | import org.apache.lucene.server.params.StructType; 30 | 31 | import net.minidev.json.JSONObject; 32 | 33 | /** Handles {@code indexStatus}. */ 34 | public class IndexStatusHandler extends Handler { 35 | private static StructType TYPE = new StructType( 36 | new Param("indexName", "Index name", new StringType())); 37 | @Override 38 | public StructType getType() { 39 | return TYPE; 40 | } 41 | 42 | @Override 43 | public String getTopDoc() { 44 | return "Returns index status (started or stopped)"; 45 | } 46 | 47 | /** Sole constructor. */ 48 | public IndexStatusHandler(GlobalState state) { 49 | super(state); 50 | } 51 | 52 | @Override 53 | public FinishRequest handle(final IndexState state, final Request r, Map> params) throws Exception { 54 | 55 | return new FinishRequest() { 56 | @Override 57 | public String finish() throws Exception { 58 | JSONObject result = new JSONObject(); 59 | result.put("status", state.isStarted() ? "started" : "stopped"); 60 | return result.toString(); 61 | } 62 | }; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/LiveSettingsHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | import org.apache.lucene.server.FinishRequest; 24 | import org.apache.lucene.server.GlobalState; 25 | import org.apache.lucene.server.IndexState; 26 | import org.apache.lucene.server.params.*; 27 | 28 | /** For changing index settings that can be changed while 29 | * the index is running. */ 30 | public class LiveSettingsHandler extends Handler { 31 | 32 | /** The parameters this handler accepts. */ 33 | public final static StructType TYPE = 34 | new StructType( 35 | new Param("indexName", "The index", new StringType()), 36 | new Param("maxRefreshSec", "Longest time to wait before reopening IndexSearcher (i.e., periodic background reopen).", new FloatType(), 1.0f), 37 | new Param("minRefreshSec", "Shortest time to wait before reopening IndexSearcher (i.e., when a search is waiting for a specific indexGen).", new FloatType(), .05f), 38 | new Param("maxSearcherAgeSec", "Non-current searchers older than this are pruned.", new FloatType(), 60.0f), 39 | new Param("index.ramBufferSizeMB", "Size (in MB) of IndexWriter's RAM buffer.", new FloatType(), 16.0f) 40 | ); 41 | 42 | @Override 43 | public StructType getType() { 44 | return TYPE; 45 | } 46 | 47 | @Override 48 | public String getTopDoc() { 49 | return "Change global offline or online settings for this index."; 50 | } 51 | 52 | /** Sole constructor. */ 53 | public LiveSettingsHandler(GlobalState state) { 54 | super(state); 55 | } 56 | 57 | @Override 58 | public FinishRequest handle(final IndexState state, Request r, Map> params) throws Exception { 59 | 60 | // TODO: should this be done inside finish? Ie, so it's 61 | // "all or no change"? 62 | if (r.hasParam("maxRefreshSec")) { 63 | state.setMaxRefreshSec(r.getFloat("maxRefreshSec")); 64 | } 65 | if (r.hasParam("minRefreshSec")) { 66 | state.setMinRefreshSec(r.getFloat("minRefreshSec")); 67 | } 68 | if (r.hasParam("maxSearcherAgeSec")) { 69 | state.setMaxSearcherAgeSec(r.getFloat("maxSearcherAgeSec")); 70 | } 71 | if (r.hasParam("index.ramBufferSizeMB")) { 72 | state.setIndexRAMBufferSizeMB(r.getFloat("index.ramBufferSizeMB")); 73 | } 74 | 75 | return new FinishRequest() { 76 | @Override 77 | public String finish() { 78 | return state.getLiveSettingsJSON(); 79 | } 80 | }; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/NewNRTPointHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.InputStream; 21 | import java.io.OutputStream; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | import org.apache.lucene.server.FinishRequest; 26 | import org.apache.lucene.server.GlobalState; 27 | import org.apache.lucene.server.IndexState; 28 | import org.apache.lucene.server.ShardState; 29 | import org.apache.lucene.server.ShardState; 30 | import org.apache.lucene.server.params.Param; 31 | import org.apache.lucene.server.params.Request; 32 | import org.apache.lucene.server.params.StringType; 33 | import org.apache.lucene.server.params.StructType; 34 | import org.apache.lucene.store.DataInput; 35 | import org.apache.lucene.store.DataOutput; 36 | 37 | /** Invoked externally to replica, to notify it that a new NRT point was just created on the primary */ 38 | public class NewNRTPointHandler extends Handler { 39 | private static StructType TYPE = new StructType( 40 | new Param("indexName", "Index name", new StringType())); 41 | 42 | @Override 43 | public StructType getType() { 44 | return TYPE; 45 | } 46 | 47 | @Override 48 | public String getTopDoc() { 49 | return "Notifies replica that primary has just finished creating a new NRT point"; 50 | } 51 | 52 | /** Sole constructor. */ 53 | public NewNRTPointHandler(GlobalState state) { 54 | super(state); 55 | } 56 | 57 | /** True if this handler should be given a {@link DataInput} to read. */ 58 | public boolean binaryRequest() { 59 | return true; 60 | } 61 | 62 | @Override 63 | public FinishRequest handle(final IndexState state, final Request r, Map> params) throws Exception { 64 | throw new UnsupportedOperationException(); 65 | } 66 | 67 | @Override 68 | public void handleBinary(InputStream streamIn, DataInput in, DataOutput out, OutputStream streamOut) throws Exception { 69 | 70 | String indexName = in.readString(); 71 | IndexState state = globalState.getIndex(indexName); 72 | ShardState shardState = state.getShard(0); 73 | if (shardState.isReplica() == false) { 74 | throw new IllegalArgumentException("index \"" + indexName + "\" is not a replica or was not started yet"); 75 | } 76 | 77 | long version = in.readVLong(); 78 | long newPrimaryGen = in.readVLong(); 79 | shardState.nrtReplicaNode.newNRTPoint(newPrimaryGen, version); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/RAMResourceLoaderWrapper.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.ByteArrayInputStream; 21 | import java.io.FileNotFoundException; 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | 27 | import org.apache.lucene.util.ResourceLoader; 28 | 29 | /** Holds "files" in RAM, and falls back to delegate if the 30 | * resource isn't in RAM. This is used for analysis 31 | * components that specify their "files" as strings inlined 32 | * in the JSON (e.g. list of stopwords for a stop filter). */ 33 | 34 | // nocommit hacky ... e.g. how are these "files" gc'd after loading/parsing 35 | 36 | class RAMResourceLoaderWrapper implements ResourceLoader { 37 | 38 | private final Map files = new HashMap(); 39 | private final ResourceLoader delegate; 40 | 41 | /** Sole constructor. */ 42 | public RAMResourceLoaderWrapper(ResourceLoader delegate) { 43 | this.delegate = delegate; 44 | } 45 | 46 | public void add(String name, String contents) { 47 | if (files.containsKey(name)) { 48 | throw new IllegalArgumentException("name \"" + name + "\" was already added"); 49 | } 50 | files.put(name, contents); 51 | } 52 | 53 | @Override 54 | public InputStream openResource(String resource) throws IOException { 55 | String value = files.get(resource); 56 | if (value != null) { 57 | return new ByteArrayInputStream(value.getBytes("UTF-8")); 58 | } else if (delegate == null) { 59 | throw new FileNotFoundException("resource \"" + resource + "\" is not found"); 60 | } else { 61 | return delegate.openResource(resource); 62 | } 63 | } 64 | 65 | @Override 66 | public T newInstance(String cname, Class expectedType) { 67 | return delegate.newInstance(cname, expectedType); 68 | } 69 | 70 | @Override 71 | public Class findClass(String cname, Class expectedType) { 72 | return delegate.findClass(cname, expectedType); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/RefreshHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | import org.apache.lucene.server.FinishRequest; 24 | import org.apache.lucene.server.GlobalState; 25 | import org.apache.lucene.server.IndexState; 26 | import org.apache.lucene.server.ShardState; 27 | import org.apache.lucene.server.params.Param; 28 | import org.apache.lucene.server.params.Request; 29 | import org.apache.lucene.server.params.StringType; 30 | import org.apache.lucene.server.params.StructType; 31 | 32 | import net.minidev.json.JSONObject; 33 | 34 | /** Handles {@code refresh}. */ 35 | public class RefreshHandler extends Handler { 36 | private static StructType TYPE = new StructType( 37 | new Param("indexName", "Index name", new StringType())); 38 | 39 | @Override 40 | public StructType getType() { 41 | return TYPE; 42 | } 43 | 44 | @Override 45 | public String getTopDoc() { 46 | return "Refresh the latest searcher for an index"; 47 | } 48 | 49 | /** Sole constructor. */ 50 | public RefreshHandler(GlobalState state) { 51 | super(state); 52 | } 53 | 54 | @Override 55 | public FinishRequest handle(final IndexState indexState, final Request r, Map> params) throws Exception { 56 | final ShardState shardState = indexState.getShard(0); 57 | return new FinishRequest() { 58 | @Override 59 | public String finish() throws Exception { 60 | long t0 = System.nanoTime(); 61 | JSONObject result = new JSONObject(); 62 | shardState.maybeRefreshBlocking(); 63 | long t1 = System.nanoTime(); 64 | result.put("refreshTimeMS", ((t1-t0)/1000000.0)); 65 | return result.toString(); 66 | } 67 | }; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/ReleaseSnapshotHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.server.FinishRequest; 25 | import org.apache.lucene.server.GlobalState; 26 | import org.apache.lucene.server.IndexState; 27 | import org.apache.lucene.server.ShardState; 28 | import org.apache.lucene.server.params.Param; 29 | import org.apache.lucene.server.params.Request; 30 | import org.apache.lucene.server.params.StringType; 31 | import org.apache.lucene.server.params.StructType; 32 | 33 | /** Handles {@code releaseSnapshot}. */ 34 | public class ReleaseSnapshotHandler extends Handler { 35 | 36 | final static StructType TYPE = new StructType( 37 | new Param("indexName", "Index Name", new StringType()), 38 | new Param("id", "The id for this snapshot; this must have been previously created via @createSnapshot.", new StringType())); 39 | 40 | @Override 41 | public String getTopDoc() { 42 | return "Releases a snapshot previously created with @createSnapshot."; 43 | } 44 | 45 | @Override 46 | public StructType getType() { 47 | return TYPE; 48 | } 49 | 50 | /** Sole constructor. */ 51 | public ReleaseSnapshotHandler(GlobalState state) { 52 | super(state); 53 | } 54 | 55 | @Override 56 | public FinishRequest handle(final IndexState indexState, final Request r, Map> params) throws Exception { 57 | final ShardState shardState = indexState.getShard(0); 58 | final IndexState.Gens gens = new IndexState.Gens(r, "id"); 59 | 60 | return new FinishRequest() { 61 | @Override 62 | public String finish() throws IOException { 63 | 64 | // SearcherLifetimeManager pruning thread will drop 65 | // the searcher (if it's old enough) next time it 66 | // wakes up: 67 | shardState.snapshots.release(gens.indexGen); 68 | shardState.writer.deleteUnusedFiles(); 69 | shardState.snapshotGenToVersion.remove(gens.indexGen); 70 | 71 | shardState.taxoSnapshots.release(gens.taxoGen); 72 | shardState.taxoInternalWriter.deleteUnusedFiles(); 73 | indexState.decRef(gens.stateGen); 74 | 75 | return "{}"; 76 | } 77 | }; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/RollbackHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.server.FinishRequest; 25 | import org.apache.lucene.server.GlobalState; 26 | import org.apache.lucene.server.IndexState; 27 | import org.apache.lucene.server.params.*; 28 | 29 | /** Handles {@code rollback}. */ 30 | public class RollbackHandler extends Handler { 31 | 32 | private static StructType TYPE = new StructType( 33 | new Param("indexName", "Index name", new StringType())); 34 | 35 | /** Sole constructor. */ 36 | public RollbackHandler(GlobalState state) { 37 | super(state); 38 | } 39 | 40 | @Override 41 | public StructType getType() { 42 | return TYPE; 43 | } 44 | 45 | @Override 46 | public String getTopDoc() { 47 | return "Commits all pending changes to durable storage."; 48 | } 49 | 50 | @Override 51 | public FinishRequest handle(final IndexState state, Request r, Map> params) throws Exception { 52 | return new FinishRequest() { 53 | @Override 54 | public String finish() throws IOException { 55 | state.rollback(); 56 | return "{}"; 57 | } 58 | }; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/SetCommitUserDataHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | import org.apache.lucene.server.FinishRequest; 26 | import org.apache.lucene.server.GlobalState; 27 | import org.apache.lucene.server.IndexState; 28 | import org.apache.lucene.server.ShardState; 29 | import org.apache.lucene.server.params.*; 30 | 31 | import net.minidev.json.JSONObject; 32 | 33 | /** Handles {@code setCommitUserData}. */ 34 | public class SetCommitUserDataHandler extends Handler { 35 | 36 | private static StructType TYPE = new StructType( 37 | new Param("indexName", "Index name", new StringType()), 38 | new Param("userData", "Custom Map", new AnyType())); 39 | 40 | /** Sole constructor. */ 41 | public SetCommitUserDataHandler(GlobalState state) { 42 | super(state); 43 | } 44 | 45 | @Override 46 | public StructType getType() { 47 | return TYPE; 48 | } 49 | 50 | @Override 51 | public String getTopDoc() { 52 | return "Sets custom user data in the index, later retrieved with @getCommitUserData."; 53 | } 54 | 55 | @Override 56 | public FinishRequest handle(final IndexState indexState, Request r, Map> params) throws Exception { 57 | final ShardState shardState = indexState.getShard(0); 58 | 59 | final Map userData = new HashMap(); 60 | for(Map.Entry ent : ((JSONObject) r.getAndRemoveRaw("userData")).entrySet()) { 61 | if (ent.getValue() instanceof String == false) { 62 | r.failWrongClass("userData", "all values must be String ", ent.getValue()); 63 | } 64 | userData.put(ent.getKey(), (String) ent.getValue()); 65 | } 66 | 67 | return new FinishRequest() { 68 | @Override 69 | public String finish() throws IOException { 70 | shardState.writer.setLiveCommitData(userData.entrySet()); 71 | return "{}"; 72 | } 73 | }; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/ShutdownHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.server.FinishRequest; 25 | import org.apache.lucene.server.GlobalState; 26 | import org.apache.lucene.server.IndexState; 27 | import org.apache.lucene.server.params.*; 28 | 29 | /** Handles {@code shutdown}. */ 30 | public class ShutdownHandler extends Handler { 31 | 32 | /** Sole constructor. */ 33 | public ShutdownHandler(GlobalState globalState) { 34 | super(globalState); 35 | requiresIndexName = false; 36 | } 37 | 38 | private static StructType TYPE = new StructType(); 39 | 40 | @Override 41 | public StructType getType() { 42 | return TYPE; 43 | } 44 | 45 | @Override 46 | public String getTopDoc() { 47 | return "Shut down the server."; 48 | } 49 | 50 | @Override 51 | public FinishRequest handle(final IndexState state, Request r, Map> params) throws Exception { 52 | return new FinishRequest() { 53 | @Override 54 | public String finish() throws IOException { 55 | // SimpleServer now does this because we get a chicken/egg situation otherwise! 56 | //globalState.shutdownNow.countDown(); 57 | return "{}"; 58 | } 59 | }; 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/StopIndexHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.server.FinishRequest; 25 | import org.apache.lucene.server.GlobalState; 26 | import org.apache.lucene.server.IndexState; 27 | import org.apache.lucene.server.params.Param; 28 | import org.apache.lucene.server.params.Request; 29 | import org.apache.lucene.server.params.StringType; 30 | import org.apache.lucene.server.params.StructType; 31 | 32 | /** Handles {@code stopIndex}. */ 33 | public class StopIndexHandler extends Handler { 34 | private static StructType TYPE = new StructType( 35 | new Param("indexName", "Index name", new StringType())); 36 | 37 | @Override 38 | public StructType getType() { 39 | return TYPE; 40 | } 41 | 42 | @Override 43 | public String getTopDoc() { 44 | return "Stops an index"; 45 | } 46 | 47 | /** Sole constructor. */ 48 | public StopIndexHandler(GlobalState state) { 49 | super(state); 50 | } 51 | 52 | @Override 53 | public FinishRequest handle(final IndexState state, final Request r, Map> params) throws Exception { 54 | return new FinishRequest() { 55 | @Override 56 | public String finish() throws IOException { 57 | state.close(); 58 | return "{}"; 59 | } 60 | }; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/UpdateDocumentHandler.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.handlers; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.StringReader; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.apache.lucene.server.FinishRequest; 25 | import org.apache.lucene.server.GlobalState; 26 | import org.apache.lucene.server.IndexState; 27 | import org.apache.lucene.server.params.Param; 28 | import org.apache.lucene.server.params.Request; 29 | import org.apache.lucene.server.params.StringType; 30 | import org.apache.lucene.server.params.StructType; 31 | import net.minidev.json.JSONArray; 32 | import net.minidev.json.JSONObject; 33 | import net.minidev.json.JSONValue; 34 | 35 | /** Handles {@code updateDocument}, by delegating the single 36 | * document to {@link BulkUpdateDocumentHandler}. */ 37 | public class UpdateDocumentHandler extends Handler { 38 | final StructType TYPE = new StructType( 39 | new Param("indexName", "Index Name", new StringType()), 40 | new Param("term", "Identifies which document to replace", 41 | new StructType( 42 | new Param("field", "Field", new StringType()), 43 | new Param("term", "Text", new StringType())))); 44 | 45 | @Override 46 | public StructType getType() { 47 | return TYPE; 48 | } 49 | 50 | @Override 51 | public String getTopDoc() { 52 | return "Replaces one document in the index. Returns the index generation (indexGen) that contains this added document."; 53 | } 54 | 55 | /** Sole constructor. */ 56 | public UpdateDocumentHandler(GlobalState state) { 57 | super(state); 58 | TYPE.params.putAll(AddDocumentHandler.DOCUMENT_TYPE.params); 59 | } 60 | 61 | @Override 62 | public FinishRequest handle(final IndexState state, final Request r, Map> params) throws Exception { 63 | 64 | state.verifyStarted(r); 65 | 66 | // NOTE: somewhat wasteful since we re-serialize to 67 | // string only to re-parse the JSON, but this allows 68 | // single-source (bulk) for parsing, and apps that care 69 | // about performance will use bulk APIs: 70 | 71 | JSONObject raw = r.getRawParams(); 72 | StringBuilder sb = new StringBuilder(); 73 | sb.append("{\"indexName\": \""); 74 | sb.append(state.name); 75 | sb.append("\", \"documents\": ["); 76 | sb.append(raw.toString()); 77 | sb.append("]}"); 78 | raw.clear(); 79 | 80 | final String bulkRequestString = sb.toString(); 81 | 82 | return new FinishRequest() { 83 | 84 | @Override 85 | public String finish() throws Exception { 86 | String result = globalState.getHandler("bulkUpdateDocument").handleStreamed(new StringReader(bulkRequestString), null); 87 | if (result.indexOf("errors") != -1) { 88 | JSONObject o = (JSONObject) JSONValue.parseStrict(result); 89 | if (o.containsKey("errors")) { 90 | JSONObject err = (JSONObject) ((JSONArray) o.get("errors")).get(0); 91 | throw new IllegalArgumentException((String) err.get("exception")); 92 | } 93 | } 94 | return result; 95 | } 96 | }; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/handlers/package.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | Lucene Server: handlers 20 | 21 | 22 |

Lucene Server: handlers

23 | Classes that handle each request method (search, addDocument, etc.). 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/package.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | Lucene Server 20 | 21 | 22 |

Lucene Server

23 | A basic example JSON/HTTP server showing how to use Lucene's APIs in a server context. 24 |

25 | Features/design: 26 |

    27 |
  • A number of Lucene's capabilities have been exposed: 28 | indexing documents, bulk indexing (streaming JSON), block 29 | joins, grouping, highlighting, suggest, live-values, 30 | snapshots, etc. 31 | 32 |
  • Lucene's legacy FieldCache is never used; only the 33 | faster, more RAM efficient doc values are used when you 34 | sort, group, facet on a field. 35 | 36 |
  • All searching is based on near-real-time IndexReader; you 37 | configure the minimum and maximum refresh times. 38 | 39 |
  • There is no required ID field; instead, a document is 40 | identified by the pair of the searcher version and Lucene's 41 | docID. 42 | 43 |
  • The server APIs are self documenting; point your browser 44 | at http://localhost:4000/doc to browse the available methods 45 | and parameters. 46 | 47 |
  • Error checking is strict but each error message should 48 | be easy to understand, pointing to the exact path/parameter 49 | that was problematic. It's an error if a 50 | request has unexpected parameters. 51 | 52 |
  • Write-once schema: fields must be registered up front, 53 | once, before any document is indexed with them; once a field 54 | is registered, it cannot be changed (write-once). 55 | 56 |
  • All changes (creating and configuring indices, indexing 57 | documents, etc.) are done through JSON APIs; there are no 58 | human-edited configuration files (though the server does 59 | store its index metadata in on-disk JSON files). 60 | 61 |
  • A snapshot records all configuration (registered fields, 62 | settings, etc.) in addition to the point-in-time view of the 63 | index; future searches can then reference that snapshot for 64 | searching. 65 | 66 |
  • A server thread pool handles all concurrency during 67 | indexing, so a single client thread using the bulk 68 | indexing API will take advantage of the server computer's 69 | concurrent hardware. 70 | 71 |
  • Settings are divided into live settings, which 72 | can be changed after the index is started, and ordinary 73 | settings, which cannot. 74 | 75 |
  • Limited infrastructure for plugins. 76 |
77 | 78 | 79 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/AnyType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Accepts any object. */ 21 | public class AnyType extends Type { 22 | 23 | /** Sole constructor. */ 24 | public AnyType() { 25 | } 26 | 27 | @Override 28 | public void validate(Object o) { 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/BooleanType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Type for booleans. */ 21 | public class BooleanType extends Type { 22 | 23 | /** Sole constructor. */ 24 | public BooleanType() { 25 | } 26 | 27 | @Override 28 | public void validate(Object o) { 29 | if (!(o instanceof Boolean)) { 30 | throw new IllegalArgumentException("expected Boolean but got " + o.getClass() + ": " + o); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/EnumType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | /** Type for an enumeration. */ 26 | public class EnumType extends Type { 27 | 28 | /** Maps label to description. */ 29 | final Map values; 30 | 31 | /** Sole constructor, values is alternating label1, 32 | * desc1, label2, desc2, ... */ 33 | public EnumType(String ... values) { 34 | if ((values.length & 1) != 0) { 35 | throw new IllegalArgumentException("input must be value/desc pairs"); 36 | } 37 | this.values = new HashMap(); 38 | for(int i=0;i(values.keySet()).toArray(new String[values.size()]); 50 | throw new IllegalArgumentException("expected one of " + Arrays.toString(keys) + " but got \"" + o + "\""); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/FloatType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.math.BigDecimal; 21 | 22 | /** Type for any number that could be a double. */ 23 | public class FloatType extends Type { 24 | 25 | /** Sole constructor. */ 26 | public FloatType() { 27 | } 28 | 29 | @Override 30 | public void validate(Object o) { 31 | // nocommit messy: 32 | if (!(o instanceof Float) && !(o instanceof Double) && !(o instanceof BigDecimal)) { 33 | throw new IllegalArgumentException("expected Float or Double but got " + o.getClass()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/IntType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Type for an integer. */ 21 | public class IntType extends Type { 22 | 23 | /** Sole constructor. */ 24 | public IntType() { 25 | } 26 | 27 | @Override 28 | public void validate(Object o) { 29 | if (!(o instanceof Integer)) { 30 | throw new IllegalArgumentException("expected Integer but got " + o.getClass()); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/ListType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.List; 21 | 22 | /** Type for a list of items of fixed subType. */ 23 | public class ListType extends Type { 24 | 25 | /** Type of our elements. */ 26 | public final Type subType; 27 | 28 | /** Sole constructor. */ 29 | public ListType(Type subType) { 30 | this.subType = subType; 31 | } 32 | 33 | @Override 34 | public void validate(Object _o) { 35 | if (!(_o instanceof List)) { 36 | throw new IllegalArgumentException("expected List but got " + _o.getClass()); 37 | } 38 | for(Object o2 : (List) _o) { 39 | subType.validate(o2); 40 | } 41 | } 42 | 43 | /** Returns item subType. */ 44 | public Type getSubType() { 45 | return subType; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/LongType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Type for a long. */ 21 | public class LongType extends Type { 22 | 23 | /** Sole constructor. */ 24 | public LongType() { 25 | } 26 | 27 | @Override 28 | public void validate(Object o) { 29 | if (!(o instanceof Long) && !(o instanceof Integer)) { 30 | throw new IllegalArgumentException("expected Long or Integer but got " + o.getClass()); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/OrType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Type that accepts any of the provided list of types. */ 21 | public class OrType extends Type { 22 | 23 | /** Allowed sub-types. */ 24 | public final Type[] types; 25 | 26 | /** Sole constructor. */ 27 | public OrType(Type... types) { 28 | this.types = types; 29 | } 30 | 31 | @Override 32 | public void validate(Object o) { 33 | for(Type t : types) { 34 | try { 35 | t.validate(o); 36 | return; 37 | } catch (IllegalArgumentException iae) { 38 | } 39 | } 40 | StringBuilder sb = new StringBuilder(); 41 | sb.append("expected one of "); 42 | for(int i=0;i types = new HashMap(); 37 | 38 | /** Not yet used but ... could be used in the future 39 | * to allow custom (plugin) classes to be accepted. */ 40 | public final Class baseClass; 41 | 42 | /** Default value, or null. */ 43 | public final String defaultClassName; 44 | 45 | /** Describes one sub type. */ 46 | public static class PolyEntry { 47 | 48 | /** Name of the sub-type, e.g. BM25Similarity. */ 49 | public final String name; 50 | 51 | /** Defines the sub type. */ 52 | public final StructType type; 53 | 54 | /** Description of this entry (English). */ 55 | public final String desc; 56 | 57 | /** Creates this, folding the provided params into a 58 | * new {@link StructType}. */ 59 | public PolyEntry(String name, String desc, Param... params) { 60 | this(name, desc, new StructType(params)); 61 | } 62 | 63 | /** Creates this. */ 64 | public PolyEntry(String name, String desc, StructType type) { 65 | this.name = name; 66 | this.desc = desc; 67 | this.type = type; 68 | } 69 | } 70 | 71 | @Override 72 | public void validate(Object o) { 73 | } 74 | 75 | /** No default value. */ 76 | public PolyType(Class baseClass, PolyEntry... entries) { 77 | this(baseClass, null, entries); 78 | } 79 | 80 | /** With default value. */ 81 | public PolyType(Class baseClass, String defaultClassName, PolyEntry... entries) { 82 | this.baseClass = baseClass; 83 | this.defaultClassName = defaultClassName; 84 | for(PolyEntry e : entries) { 85 | if (types.containsKey(e.name)) { 86 | throw new IllegalArgumentException("name \"" + e.name + "\" appears more than once"); 87 | } 88 | types.put(e.name, e); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/RequestFailedException.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | // nocommit rename to InvalidRequestExc? 21 | 22 | /** Exception thrown on an invalid request. */ 23 | public class RequestFailedException extends IllegalArgumentException { 24 | 25 | /** The request that contains the failure. */ 26 | public final Request request; 27 | 28 | /** Which parameter led to the failure, if any (can be 29 | * null). */ 30 | public final String param; 31 | 32 | /** The full path leading to the parameter (e.g., 33 | * sort.fields[0].field). */ 34 | public final String path; 35 | 36 | /** The specific reason for the failure (e.g., "expected 37 | * int but got string"). */ 38 | public final String reason; 39 | 40 | /** Creates this. */ 41 | public RequestFailedException(Request r, String param, String path, String reason) { 42 | super(path + ": " + reason); 43 | this.request = r; 44 | this.param = param; 45 | this.path = path; 46 | this.reason = reason; 47 | } 48 | 49 | /** Creates this from another {@code 50 | * RequestFailedException}, adding further details. */ 51 | public RequestFailedException(RequestFailedException other, String details) { 52 | super(other.reason + ": " + details); 53 | this.reason = other.reason + ": " + details; 54 | this.request = other.request; 55 | this.param = other.param; 56 | this.path = other.path; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/StringType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Type for a string. */ 21 | public class StringType extends Type { 22 | 23 | /** Sole constructor. */ 24 | public StringType() { 25 | } 26 | 27 | @Override 28 | public void validate(Object o) { 29 | if (!(o instanceof String)) { 30 | throw new IllegalArgumentException("expected String but got " + o.getClass()); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/StructType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | 23 | import net.minidev.json.JSONObject; 24 | 25 | /** Type for a structure containing named typed parameters. */ 26 | public class StructType extends Type { 27 | 28 | /** Parameters contained in this struct. */ 29 | public final Map params = new HashMap(); 30 | 31 | /** Sole constructor. */ 32 | public StructType(Param... params) { 33 | boolean sawPoly = false; 34 | for(Param p : params) { 35 | if (this.params.containsKey(p.name)) { 36 | throw new IllegalArgumentException("param name \"" + p.name + "\" appears more than once"); 37 | } 38 | if (p.type instanceof PolyType) { 39 | if (sawPoly) { 40 | throw new IllegalArgumentException("only one PolyType per struct"); 41 | } 42 | sawPoly = true; 43 | } 44 | this.params.put(p.name, p); 45 | } 46 | } 47 | 48 | /** Add another parameter. */ 49 | public void addParam(Param param) { 50 | if (params.containsKey(param.name)) { 51 | throw new IllegalArgumentException("param name \"" + param.name + "\" already exists"); 52 | } 53 | params.put(param.name, param); 54 | } 55 | 56 | @Override 57 | public void validate(Object _o) { 58 | if (!(_o instanceof JSONObject)) { 59 | throw new IllegalArgumentException("expected struct but got " + _o.getClass()); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/Type.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Base class for al types. */ 21 | public abstract class Type { 22 | 23 | /** Sole constructor. */ 24 | protected Type() { 25 | } 26 | 27 | /** Confirms that the object is a valid item matching the 28 | * type; if it is not, throw {@code 29 | * IllegalArgumentException}. */ 30 | public abstract void validate(Object o); 31 | } 32 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/WrapType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.params; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Wraps another type; use this to break type recursion. */ 21 | public class WrapType extends Type { 22 | private Type other; 23 | 24 | /** Sole constructor. */ 25 | public WrapType() { 26 | } 27 | 28 | /** Set our wrapped type. */ 29 | public void set(Type other) { 30 | if (this.other != null) { 31 | throw new IllegalStateException("already set"); 32 | } 33 | 34 | this.other = other; 35 | } 36 | 37 | @Override 38 | public void validate(Object o) { 39 | other.validate(o); 40 | } 41 | 42 | /** Return the type we wrap. */ 43 | public Type getWrappedType() { 44 | return other; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/params/package.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | Lucene Server: params 20 | 21 | 22 |

Lucene Server: params

23 | Classes to handle matching incoming JSON requests against declared expected types. 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/plugins/Plugin.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server.plugins; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | /** Base class for all plugins. */ 21 | public abstract class Plugin { 22 | 23 | /** Sole constructor. */ 24 | public Plugin() { 25 | } 26 | 27 | /** Name of this plugin. */ 28 | public abstract String getName(); 29 | 30 | /** Documentation for this plugin (English). */ 31 | public abstract String getTopDoc(); 32 | } 33 | -------------------------------------------------------------------------------- /src/java/org/apache/lucene/server/plugins/package.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | Lucene Server: plugins 20 | 21 | 22 |

Lucene Server: plugins

23 | Classes to handle plugins. 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/MockPlugin-hello.txt: -------------------------------------------------------------------------------- 1 | hello world! 2 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/MockPlugin-lucene-server-plugin.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | class: org.apache.lucene.server.MockPlugin 17 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/MockPlugin.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.apache.lucene.server.handlers.Handler; 21 | import org.apache.lucene.server.params.IntType; 22 | import org.apache.lucene.server.params.Param; 23 | import org.apache.lucene.server.params.Request; 24 | import org.apache.lucene.server.params.StructType; 25 | import org.apache.lucene.server.plugins.Plugin; 26 | import net.minidev.json.JSONObject; 27 | 28 | public class MockPlugin extends Plugin { 29 | 30 | @Override 31 | public String getTopDoc() { 32 | return "Adds foobar param to AddDocument"; 33 | } 34 | 35 | @Override 36 | public String getName() { 37 | return "Mock"; 38 | } 39 | 40 | private static class AddDocumentPreHandler implements PreHandle { 41 | 42 | @Override 43 | public void invoke(Request r) { 44 | Request r2 = r.getStruct("fields"); 45 | if (r2.hasParam("mockFoobar")) { 46 | int x = r2.getInt("mockFoobar"); 47 | JSONObject params = r2.getRawParams(); 48 | params.put("intfield", 2*x); 49 | } 50 | } 51 | } 52 | 53 | public MockPlugin(GlobalState state) { 54 | Handler addDocHandler = state.getHandler("addDocument"); 55 | 56 | // Register our pre-processor in addDocument: 57 | addDocHandler.addPreHandle(new AddDocumentPreHandler()); 58 | 59 | StructType fieldsType = ((StructType) addDocHandler.getType().params.get("fields").type); 60 | 61 | fieldsType.addParam(new Param("mockFoobar", "Testing adding a new silly param", new IntType())); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/TermFreqPayload.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.apache.lucene.util.BytesRef; 21 | 22 | public final class TermFreqPayload { 23 | public final BytesRef term; 24 | public final long v; 25 | public final BytesRef payload; 26 | 27 | public TermFreqPayload(String term, long v, BytesRef payload) { 28 | this(new BytesRef(term), v, payload); 29 | } 30 | 31 | public TermFreqPayload(BytesRef term, long v, BytesRef payload) { 32 | this.term = term; 33 | this.v = v; 34 | this.payload = payload; 35 | } 36 | } -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/TestBooleanFieldType.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | 22 | import org.junit.AfterClass; 23 | import org.junit.BeforeClass; 24 | 25 | import net.minidev.json.JSONObject; 26 | 27 | public class TestBooleanFieldType extends ServerBaseTestCase { 28 | 29 | @BeforeClass 30 | public static void initClass() throws Exception { 31 | useDefaultIndex = true; 32 | startServer(); 33 | createAndStartIndex("index"); 34 | registerFields(); 35 | commit(); 36 | } 37 | 38 | @AfterClass 39 | public static void fini() throws Exception { 40 | shutdownServer(); 41 | } 42 | 43 | private static void registerFields() throws Exception { 44 | JSONObject o = new JSONObject(); 45 | put(o, "id", "{type: int, store: true}"); 46 | put(o, "other", "{type: text, store: true}"); 47 | put(o, "flagStored", "{type: boolean, store: true, search: false}"); 48 | put(o, "flagIndexed", "{type: boolean, store: false, search: true}"); 49 | JSONObject o2 = new JSONObject(); 50 | o2.put("indexName", "index"); 51 | o2.put("fields", o); 52 | send("registerFields", o2); 53 | } 54 | 55 | public void testStored() throws Exception { 56 | deleteAllDocs(); 57 | send("addDocument", "{fields: {id: 0, flagStored: false}}"); 58 | long gen = getLong(send("addDocument", "{fields: {id: 1, flagStored: true}}"), "indexGen"); 59 | JSONObject o = send("search", "{searcher: {indexGen: " + gen + "}, query: MatchAllDocsQuery, retrieveFields: [id, flagStored]}"); 60 | assertEquals(2, getInt(o, "totalHits.value")); 61 | assertFalse(getBoolean(o, "hits[0].fields.flagStored")); 62 | assertTrue(getBoolean(o, "hits[1].fields.flagStored")); 63 | } 64 | 65 | public void testIndexed() throws Exception { 66 | deleteAllDocs(); 67 | send("addDocument", "{fields: {id: 0, flagIndexed: false, flagStored: false}}"); 68 | long gen = getLong(send("addDocument", "{fields: {id: 1, flagIndexed: true, flagStored: true}}"), "indexGen"); 69 | JSONObject o = send("search", "{searcher: {indexGen: " + gen + "}, query: {class: BooleanFieldQuery, field: flagIndexed}, retrieveFields: [id, flagStored]}"); 70 | assertEquals(1, getInt(o, "totalHits.value")); 71 | assertTrue(getBoolean(o, "hits[0].fields.flagStored")); 72 | } 73 | 74 | public void testWrongFieldType() throws Exception { 75 | deleteAllDocs(); 76 | send("addDocument", "{fields: {id: 0, other: \"foo\", flagIndexed: false, flagStored: false}}"); 77 | long gen = getLong(send("addDocument", "{fields: {id: 1, flagIndexed: true, flagStored: true}}"), "indexGen"); 78 | Exception e = expectThrows(IOException.class, () -> {send("search", "{searcher: {indexGen: " + gen + "}, query: {class: BooleanFieldQuery, field: other}, retrieveFields: [id, flagStored]}");}); 79 | assertEquals("Server error:\nsearch > query > field: field \"other\" must be valueType=boolean but got: TEXT", e.getMessage()); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/TestCommitUserData.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.junit.AfterClass; 21 | import org.junit.BeforeClass; 22 | 23 | public class TestCommitUserData extends ServerBaseTestCase { 24 | @BeforeClass 25 | public static void initClass() throws Exception { 26 | useDefaultIndex = true; 27 | startServer(); 28 | createAndStartIndex("index"); 29 | } 30 | 31 | @AfterClass 32 | public static void fini() throws Exception { 33 | shutdownServer(); 34 | } 35 | 36 | /** Make sure we can set commit data even when there are 37 | * not docs */ 38 | public void testEmpty() throws Exception { 39 | send("setCommitUserData", "{userData: {a: c, b: d}}"); 40 | send("getCommitUserData"); 41 | assertEquals("c", getString("a")); 42 | assertEquals("d", getString("b")); 43 | bounceServer(); 44 | send("startIndex"); 45 | send("getCommitUserData"); 46 | assertEquals("c", getString("a")); 47 | assertEquals("d", getString("b")); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/TestCustomDirectory.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.nio.file.Path; 22 | 23 | import org.apache.lucene.store.MMapDirectory; 24 | import org.junit.AfterClass; 25 | import org.junit.BeforeClass; 26 | 27 | public class TestCustomDirectory extends ServerBaseTestCase { 28 | 29 | @BeforeClass 30 | public static void initClass() throws Exception { 31 | useDefaultIndex = false; 32 | startServer(); 33 | } 34 | 35 | @AfterClass 36 | public static void fini() throws Exception { 37 | shutdownServer(); 38 | } 39 | 40 | private static boolean iWasUsed; 41 | 42 | public static class MyDirectory extends MMapDirectory { 43 | public MyDirectory(Path path) throws IOException { 44 | super(path); 45 | iWasUsed = true; 46 | } 47 | } 48 | 49 | public void testCustomDirectory() throws Exception { 50 | createIndex("index"); 51 | send("settings", "{directory: org.apache.lucene.server.TestCustomDirectory$MyDirectory}"); 52 | send("startIndex"); 53 | send("stopIndex"); 54 | send("deleteIndex"); 55 | assertTrue(iWasUsed); 56 | } 57 | 58 | public void testInvalidDirectory() throws Exception { 59 | createIndex("index"); 60 | assertFailsWith("settings", "{directory: bad}", "could not locate Directory sub-class \"bad\"; verify CLASSPATH"); 61 | send("deleteIndex"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/TestNumericFields.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.junit.AfterClass; 21 | import org.junit.BeforeClass; 22 | import net.minidev.json.JSONObject; 23 | 24 | public class TestNumericFields extends ServerBaseTestCase { 25 | 26 | @BeforeClass 27 | public static void initClass() throws Exception { 28 | useDefaultIndex = true; 29 | startServer(); 30 | createAndStartIndex("index"); 31 | registerFields(); 32 | commit(); 33 | } 34 | 35 | @AfterClass 36 | public static void fini() throws Exception { 37 | shutdownServer(); 38 | } 39 | 40 | private static void registerFields() throws Exception { 41 | JSONObject o = new JSONObject(); 42 | put(o, "intNoSort", "{type: int, store: true}"); 43 | put(o, "intSort", "{type: int, sort: true, store: true}"); 44 | put(o, "floatNoSort", "{type: float, store: true}"); 45 | put(o, "floatSort", "{type: float, sort: true, store: true}"); 46 | JSONObject o2 = new JSONObject(); 47 | o2.put("fields", o); 48 | o2.put("indexName", "index"); 49 | send("registerFields", o2); 50 | } 51 | 52 | public void testRetrieve() throws Exception { 53 | deleteAllDocs(); 54 | long gen = getLong(send("addDocument", "{fields: {intNoSort: 17, intSort: 22, floatNoSort: 17.0, floatSort: 22.0}}"), "indexGen"); 55 | JSONObject result = send("search", "{retrieveFields: [intNoSort, intSort, floatNoSort, floatSort], query: MatchAllDocsQuery, searcher: {indexGen: " + gen + "}}"); 56 | assertEquals(1, getInt(result, "totalHits.value")); 57 | assertEquals(17, getInt(result, "hits[0].fields.intNoSort")); 58 | assertEquals(22, getInt(result, "hits[0].fields.intSort")); 59 | assertEquals(17.0f, getFloat(result, "hits[0].fields.floatNoSort"), 1e-7); 60 | assertEquals(22.0f, getFloat(result, "hits[0].fields.floatSort"), 1e-7); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/TestPlugins.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import java.io.FileOutputStream; 21 | import java.io.InputStream; 22 | import java.nio.file.Files; 23 | import java.nio.file.Path; 24 | import java.util.zip.ZipEntry; 25 | import java.util.zip.ZipOutputStream; 26 | 27 | import org.junit.AfterClass; 28 | import org.junit.BeforeClass; 29 | 30 | import net.minidev.json.JSONObject; 31 | 32 | public class TestPlugins extends ServerBaseTestCase { 33 | 34 | @BeforeClass 35 | public static void init() throws Exception { 36 | useDefaultIndex = false; 37 | Path tmpDir = createTempDir("TestPlugins"); 38 | Files.createDirectories(tmpDir); 39 | Path zipFile = tmpDir.resolve("MockPlugin-0.1.zip"); 40 | ZipOutputStream os = new ZipOutputStream(new FileOutputStream(zipFile.toFile())); 41 | addToZip(os, "Mock/org/apache/lucene/server/MockPlugin.class", "MockPlugin.class"); 42 | addToZip(os, "Mock/lucene-server-plugin.properties", "MockPlugin-lucene-server-plugin.properties"); 43 | addToZip(os, "Mock/site/hello.txt", "MockPlugin-hello.txt"); 44 | os.close(); 45 | installPlugin(zipFile); 46 | startServer(); 47 | } 48 | 49 | static void addToZip(ZipOutputStream dest, String zipName, String resourcePath) throws Exception { 50 | ZipEntry file = new ZipEntry(zipName); 51 | dest.putNextEntry(file); 52 | try (InputStream input = TestPlugins.class.getResourceAsStream(resourcePath)) { 53 | byte buf[] = new byte[1024]; 54 | int numRead; 55 | while ((numRead = input.read(buf)) >= 0) { 56 | dest.write(buf, 0, numRead); 57 | } 58 | } 59 | dest.closeEntry(); 60 | } 61 | 62 | @AfterClass 63 | public static void fini() throws Exception { 64 | shutdownServer(); 65 | } 66 | 67 | // nocommit this test should install from zip file (call installPlugin(...)) 68 | 69 | public void testMockPlugin() throws Exception { 70 | 71 | // Make sure docs reflect new mockFoobar: 72 | String doc = httpLoad("doc?method=addDocument"); 73 | assertTrue(doc.indexOf("mockFoobar") != -1); 74 | 75 | // nocommit test docs: verify foobar is there 76 | // nocommit need a "list plugins" API: verify foobar is there 77 | // nocommit send addDocument & verify change "took" 78 | 79 | createAndStartIndex("index"); 80 | send("registerFields", "{fields: {id: {type: int, store: true}, intfield: {type: int, store: true}}}"); 81 | long gen = getLong(send("addDocument", "{fields: {id: 0, mockFoobar: 7}}"), "indexGen"); 82 | 83 | JSONObject result = send("search", "{searcher: {indexGen: " + gen + "}, query: MatchAllDocsQuery, retrieveFields: [id, intfield]}"); 84 | assertEquals(1, getInt(result, "totalHits.value")); 85 | assertEquals(14, getInt(result, "hits[0].fields.intfield")); 86 | //System.out.println("got: " + prettyPrint(result)); 87 | } 88 | 89 | /** Make sure a plugin can have/serve a static file. */ 90 | public void testStaticFile() throws Exception { 91 | String contents = httpLoad("plugins/Mock/hello.txt"); 92 | assertEquals("hello world!\n", contents); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/TestSettings.java: -------------------------------------------------------------------------------- 1 | package org.apache.lucene.server; 2 | 3 | /* 4 | * Licensed to the Apache Software Foundation (ASF) under one or more 5 | * contributor license agreements. See the NOTICE file distributed with 6 | * this work for additional information regarding copyright ownership. 7 | * The ASF licenses this file to You under the Apache License, Version 2.0 8 | * (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | import org.junit.AfterClass; 21 | import org.junit.BeforeClass; 22 | import net.minidev.json.JSONObject; 23 | 24 | public class TestSettings extends ServerBaseTestCase { 25 | 26 | @BeforeClass 27 | public static void initClass() throws Exception { 28 | useDefaultIndex = true; 29 | startServer(); 30 | createAndStartIndex("index"); 31 | registerFields(); 32 | commit(); 33 | } 34 | 35 | @AfterClass 36 | public static void fini() throws Exception { 37 | shutdownServer(); 38 | } 39 | 40 | private static void registerFields() throws Exception { 41 | send("registerFields", "{fields: {body: {type: text, analyzer: StandardAnalyzer}}}"); 42 | } 43 | 44 | public void testNRTCachingDirSettings() throws Exception { 45 | deleteAllDocs(); 46 | commit(); 47 | send("stopIndex"); 48 | JSONObject o = send("settings"); 49 | assertEquals(0, o.size()); 50 | // Turn off NRTCachingDir: 51 | send("settings", "{nrtCachingDirectory.maxMergeSizeMB: 0.0, nrtCachingDirectory.maxSizeMB: 0.0}"); 52 | o = send("settings"); 53 | assertEquals(2, o.size()); 54 | send("startIndex"); 55 | long gen = getLong(send("addDocument", "{fields: {body: 'here is a test'}}"), "indexGen"); 56 | assertEquals(1, getInt(send("search", "{queryText: test, searcher: {indexGen: " + gen + "}}"), "totalHits.value")); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/org/apache/lucene/server/convertWiki.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | id = 0 4 | pending = [] 5 | pendingByteCount = 0 6 | pendingDocCount = 0 7 | with open('/lucenedata/enwiki/enwiki-20120502-lines-1k-fixed-utf8.txt', 'r', encoding='utf-8') as f, open('/lucenedata/enwiki/enwiki-20120502-lines-1k-fixed-utf8.txt.blocks', 'wb') as fOut: 8 | f.readline() 9 | while True: 10 | line = f.readline() 11 | if line == '': 12 | break 13 | title, date, body = line.split('\t') 14 | if id > 0: 15 | pending.append(',\n'.encode('utf-8')) 16 | pendingByteCount += 2 17 | s = json.dumps({'fields': {'body': body, 'title': title, 'id': id}}).encode('utf-8') 18 | pending.append(s) 19 | pendingByteCount += len(s) 20 | pendingDocCount += 1 21 | id += 1 22 | 23 | if pendingByteCount > 128*1024: 24 | fOut.write(('%d %d\n' % (pendingByteCount, pendingDocCount)).encode('utf-8')) 25 | fOut.write(b''.join(pending)) 26 | pending.clear() 27 | pendingByteCount = 0 28 | pendingDocCount = 0 29 | --------------------------------------------------------------------------------