Tarantool/Box, or simply Tarantool, is a high performance key/value
storage server. The code is available for free under the terms of BSD license. Supported platforms are GNU/Linux and FreeBSD. WWW: http://tarantool.org/ PR: ports/163213 Submitted by: Gvozdikov Veniamin <g.veniamin@googlemail.com>
This commit is contained in:
parent
2f2516d4df
commit
4ca7312e0e
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=288420
17 changed files with 1006 additions and 0 deletions
|
@ -803,6 +803,7 @@
|
|||
SUBDIR += squirrel-sql
|
||||
SUBDIR += sybtcl
|
||||
SUBDIR += tablelog
|
||||
SUBDIR += tarantool
|
||||
SUBDIR += tcl-Mysql
|
||||
SUBDIR += tdb
|
||||
SUBDIR += tinycdb
|
||||
|
|
43
databases/tarantool/Makefile
Normal file
43
databases/tarantool/Makefile
Normal file
|
@ -0,0 +1,43 @@
|
|||
# New ports collection makefile for: tarantool
|
||||
# Date created: 2011-11-25
|
||||
# Whom: Gvozdikov Veniamin <g.veniamin@googlemail.com>
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
PORTNAME= tarantool
|
||||
PORTVERSION= 1.3.5
|
||||
CATEGORIES= databases
|
||||
MASTER_SITES= http://launchpadlibrarian.net/71705094/
|
||||
DISTNAME= ${PORTNAME}-${PORTVERSION}-src
|
||||
|
||||
MAINTAINER= g.veniamin@googlemail.com
|
||||
COMMENT= Tarantool, is a high performance key/value storage server
|
||||
|
||||
LICENSE= BSD
|
||||
|
||||
ONLY_FOR_ARCHS= i386
|
||||
|
||||
USE_CMAKE= yes
|
||||
ARCH= i386
|
||||
USE_RC_SUBR= ${PORTNAME}
|
||||
SUB_FILES= pkg-message
|
||||
|
||||
.include <bsd.port.pre.mk>
|
||||
|
||||
post-patch:
|
||||
@${REINPLACE_CMD} -e 's|%%DOCSDIR%%|${DOCSDIR}|g' \
|
||||
${WRKSRC}/CMakeLists.txt
|
||||
@${REINPLACE_CMD} -e 's|%%ETCDIR%%|${ETCDIR}|g' \
|
||||
${WRKSRC}/test/CMakeLists.txt
|
||||
@${RM} ${WRKSRC}/test/lib/server.py \
|
||||
${WRKSRC}/test/lib/silverbox.py \
|
||||
${WRKSRC}/test/lib/tarantool_admin.py \
|
||||
${WRKSRC}/test/lib/tarantool_feeder_server.py \
|
||||
${WRKSRC}/test/lib/tarantool_server.py \
|
||||
${WRKSRC}/test/lib/*.orig
|
||||
|
||||
post-install:
|
||||
@${CAT} ${PKGMESSAGE}
|
||||
|
||||
.include <bsd.port.post.mk>
|
2
databases/tarantool/distinfo
Normal file
2
databases/tarantool/distinfo
Normal file
|
@ -0,0 +1,2 @@
|
|||
SHA256 (tarantool-1.3.5-src.tar.gz) = c78eb302eabac7b6ae04a8eadf8b2819e992d2913cdafe1a86222148982351ec
|
||||
SIZE (tarantool-1.3.5-src.tar.gz) = 829327
|
11
databases/tarantool/files/patch-CMakeLists.txt
Normal file
11
databases/tarantool/files/patch-CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
--- CMakeLists.txt.orig 2011-11-25 15:33:08.997444924 +0000
|
||||
+++ CMakeLists.txt 2011-11-25 15:33:30.428593855 +0000
|
||||
@@ -197,7 +197,7 @@
|
||||
add_subdirectory(test)
|
||||
|
||||
install (FILES README LICENSE doc/silverbox-protocol.txt
|
||||
- DESTINATION doc)
|
||||
+ DESTINATION %%DOCSDIR%%)
|
||||
|
||||
include (cmake/tarantool_cpack.cmake)
|
||||
#
|
9
databases/tarantool/files/patch-test_CMakeLists.txt
Normal file
9
databases/tarantool/files/patch-test_CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
--- test/CMakeLists.txt.orig 2011-12-11 16:16:40.594230551 +0000
|
||||
+++ test/CMakeLists.txt 2011-12-11 16:19:44.915010706 +0000
|
||||
@@ -9,5 +9,4 @@
|
||||
|
||||
install (PROGRAMS tarantool DESTINATION bin)
|
||||
install (DIRECTORY lib DESTINATION bin)
|
||||
-install (FILES box/tarantool.cfg box/00000000000000000001.snap
|
||||
- DESTINATION bin)
|
||||
+install (FILES box/tarantool.cfg DESTINATION %%ETCDIR%%)
|
17
databases/tarantool/files/patch-test_box_tarantool.cfg
Normal file
17
databases/tarantool/files/patch-test_box_tarantool.cfg
Normal file
|
@ -0,0 +1,17 @@
|
|||
--- test/box/tarantool.cfg.orig 2011-12-13 01:02:02.069760259 +0000
|
||||
+++ test/box/tarantool.cfg 2011-12-13 01:03:52.550055101 +0000
|
||||
@@ -1,11 +1,11 @@
|
||||
slab_alloc_arena = 0.1
|
||||
|
||||
-pid_file = "box.pid"
|
||||
-
|
||||
+pid_file = "/var/run/tarantool.pid"
|
||||
+work_dir = "/var/db/tarantool"
|
||||
|
||||
# Use -a not -a to work correctly on FreeBSD
|
||||
#
|
||||
-logger="tee -a tarantool.log"
|
||||
+logger="cat >> /var/log/tarantool.log"
|
||||
|
||||
primary_port = 33013
|
||||
secondary_port = 33014
|
57
databases/tarantool/files/patch-test_lib_sql.g
Normal file
57
databases/tarantool/files/patch-test_lib_sql.g
Normal file
|
@ -0,0 +1,57 @@
|
|||
--- test/lib/sql.g.orig 2011-05-14 12:16:32.000000000 +0000
|
||||
+++ test/lib/sql.g 2011-12-13 00:41:37.729004939 +0000
|
||||
@@ -5,10 +5,6 @@
|
||||
|
||||
%%
|
||||
|
||||
-# The grammar below solely covers the functionality provided by
|
||||
-# Tarantool binary protocol, from which follow all the
|
||||
-# limitations. For reference please see doc/box-protocol.txt.
|
||||
-
|
||||
parser sql:
|
||||
|
||||
ignore: '\\s+'
|
||||
@@ -25,8 +21,6 @@
|
||||
token WHERE: 'where'
|
||||
token VALUES: 'values'
|
||||
token SET: 'set'
|
||||
- token OR: 'or'
|
||||
- token LIMIT: 'limit'
|
||||
token END: '\\s*$'
|
||||
|
||||
rule sql: (insert {{ stmt = insert }} |
|
||||
@@ -37,27 +31,19 @@
|
||||
|
||||
rule insert: INSERT [INTO] ident VALUES value_list
|
||||
{{ return sql_ast.StatementInsert(ident, value_list) }}
|
||||
- rule update: UPDATE ident SET update_list opt_simple_where
|
||||
- {{ return sql_ast.StatementUpdate(ident, update_list, opt_simple_where) }}
|
||||
- rule delete: DELETE FROM ident opt_simple_where
|
||||
- {{ return sql_ast.StatementDelete(ident, opt_simple_where) }}
|
||||
- rule select: SELECT '\*' FROM ident opt_where opt_limit
|
||||
- {{ return sql_ast.StatementSelect(ident, opt_where, opt_limit) }}
|
||||
+ rule update: UPDATE ident SET update_list opt_where
|
||||
+ {{ return sql_ast.StatementUpdate(ident, update_list, opt_where) }}
|
||||
+ rule delete: DELETE FROM ident opt_where
|
||||
+ {{ return sql_ast.StatementDelete(ident, opt_where) }}
|
||||
+ rule select: SELECT '\*' FROM ident opt_where
|
||||
+ {{ return sql_ast.StatementSelect(ident, opt_where) }}
|
||||
rule ping: PING
|
||||
{{ return sql_ast.StatementPing() }}
|
||||
rule predicate: ident '=' constant
|
||||
{{ return (ident, constant) }}
|
||||
- rule opt_simple_where: {{ return None }}
|
||||
+ rule opt_where: {{ return None }}
|
||||
| WHERE predicate
|
||||
{{ return predicate }}
|
||||
- rule opt_where: {{ return None }}
|
||||
- | WHERE disjunction
|
||||
- {{ return disjunction }}
|
||||
- rule disjunction: predicate {{ disjunction = [predicate] }}
|
||||
- [(OR predicate {{ disjunction.append(predicate) }})+]
|
||||
- {{ return disjunction }}
|
||||
- rule opt_limit: {{ return 0xffffffff }}
|
||||
- | LIMIT NUM {{ return int(NUM) }}
|
||||
rule value_list: '\(' expr {{ value_list = [expr] }}
|
||||
[("," expr {{ value_list.append(expr) }} )+]
|
||||
'\)' {{ return value_list }}
|
92
databases/tarantool/files/patch-test_lib_sql.py
Normal file
92
databases/tarantool/files/patch-test_lib_sql.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
--- test/lib/sql.py.orig 2011-05-14 12:16:32.000000000 +0000
|
||||
+++ test/lib/sql.py 2011-12-13 00:23:04.673107891 +0000
|
||||
@@ -30,8 +30,6 @@
|
||||
('WHERE', re.compile('where')),
|
||||
('VALUES', re.compile('values')),
|
||||
('SET', re.compile('set')),
|
||||
- ('OR', re.compile('or')),
|
||||
- ('LIMIT', re.compile('limit')),
|
||||
('END', re.compile('\\s*$')),
|
||||
]
|
||||
def __init__(self, str,*args,**kw):
|
||||
@@ -76,16 +74,16 @@
|
||||
ident = self.ident(_context)
|
||||
SET = self._scan('SET', context=_context)
|
||||
update_list = self.update_list(_context)
|
||||
- opt_simple_where = self.opt_simple_where(_context)
|
||||
- return sql_ast.StatementUpdate(ident, update_list, opt_simple_where)
|
||||
+ opt_where = self.opt_where(_context)
|
||||
+ return sql_ast.StatementUpdate(ident, update_list, opt_where)
|
||||
|
||||
def delete(self, _parent=None):
|
||||
_context = self.Context(_parent, self._scanner, 'delete', [])
|
||||
DELETE = self._scan('DELETE', context=_context)
|
||||
FROM = self._scan('FROM', context=_context)
|
||||
ident = self.ident(_context)
|
||||
- opt_simple_where = self.opt_simple_where(_context)
|
||||
- return sql_ast.StatementDelete(ident, opt_simple_where)
|
||||
+ opt_where = self.opt_where(_context)
|
||||
+ return sql_ast.StatementDelete(ident, opt_where)
|
||||
|
||||
def select(self, _parent=None):
|
||||
_context = self.Context(_parent, self._scanner, 'select', [])
|
||||
@@ -94,8 +92,7 @@
|
||||
FROM = self._scan('FROM', context=_context)
|
||||
ident = self.ident(_context)
|
||||
opt_where = self.opt_where(_context)
|
||||
- opt_limit = self.opt_limit(_context)
|
||||
- return sql_ast.StatementSelect(ident, opt_where, opt_limit)
|
||||
+ return sql_ast.StatementSelect(ident, opt_where)
|
||||
|
||||
def ping(self, _parent=None):
|
||||
_context = self.Context(_parent, self._scanner, 'ping', [])
|
||||
@@ -109,8 +106,8 @@
|
||||
constant = self.constant(_context)
|
||||
return (ident, constant)
|
||||
|
||||
- def opt_simple_where(self, _parent=None):
|
||||
- _context = self.Context(_parent, self._scanner, 'opt_simple_where', [])
|
||||
+ def opt_where(self, _parent=None):
|
||||
+ _context = self.Context(_parent, self._scanner, 'opt_where', [])
|
||||
_token = self._peek('WHERE', 'END', context=_context)
|
||||
if _token == 'END':
|
||||
return None
|
||||
@@ -119,38 +116,6 @@
|
||||
predicate = self.predicate(_context)
|
||||
return predicate
|
||||
|
||||
- def opt_where(self, _parent=None):
|
||||
- _context = self.Context(_parent, self._scanner, 'opt_where', [])
|
||||
- _token = self._peek('WHERE', 'LIMIT', 'END', context=_context)
|
||||
- if _token != 'WHERE':
|
||||
- return None
|
||||
- else: # == 'WHERE'
|
||||
- WHERE = self._scan('WHERE', context=_context)
|
||||
- disjunction = self.disjunction(_context)
|
||||
- return disjunction
|
||||
-
|
||||
- def disjunction(self, _parent=None):
|
||||
- _context = self.Context(_parent, self._scanner, 'disjunction', [])
|
||||
- predicate = self.predicate(_context)
|
||||
- disjunction = [predicate]
|
||||
- if self._peek('OR', 'LIMIT', 'END', context=_context) == 'OR':
|
||||
- while 1:
|
||||
- OR = self._scan('OR', context=_context)
|
||||
- predicate = self.predicate(_context)
|
||||
- disjunction.append(predicate)
|
||||
- if self._peek('OR', 'LIMIT', 'END', context=_context) != 'OR': break
|
||||
- return disjunction
|
||||
-
|
||||
- def opt_limit(self, _parent=None):
|
||||
- _context = self.Context(_parent, self._scanner, 'opt_limit', [])
|
||||
- _token = self._peek('LIMIT', 'END', context=_context)
|
||||
- if _token == 'END':
|
||||
- return 0xffffffff
|
||||
- else: # == 'LIMIT'
|
||||
- LIMIT = self._scan('LIMIT', context=_context)
|
||||
- NUM = self._scan('NUM', context=_context)
|
||||
- return int(NUM)
|
||||
-
|
||||
def value_list(self, _parent=None):
|
||||
_context = self.Context(_parent, self._scanner, 'value_list', [])
|
||||
self._scan("'\\('", context=_context)
|
45
databases/tarantool/files/patch-test_lib_sql_ast.py
Normal file
45
databases/tarantool/files/patch-test_lib_sql_ast.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
--- test/lib/sql_ast.py.orig 2011-05-14 12:16:32.000000000 +0000
|
||||
+++ test/lib/sql_ast.py 2011-12-13 00:23:04.673107891 +0000
|
||||
@@ -242,22 +242,16 @@
|
||||
class StatementSelect(StatementPing):
|
||||
reqeust_type = SELECT_REQUEST_TYPE
|
||||
|
||||
- def __init__(self, table_name, where, limit):
|
||||
+ def __init__(self, table_name, where):
|
||||
self.namespace_no = table_name
|
||||
- self.index_no = None
|
||||
- self.key_list = []
|
||||
- if not where:
|
||||
- self.index_no = 0
|
||||
- self.key_list = ["",]
|
||||
+ if where:
|
||||
+ (self.index_no, key) = where
|
||||
+ self.key = [key]
|
||||
else:
|
||||
- for (index_no, key) in where:
|
||||
- self.key_list.append(key)
|
||||
- if self.index_no == None:
|
||||
- self.index_no = index_no
|
||||
- elif self.index_no != index_no:
|
||||
- raise RuntimeError("All key values in a disjunction must refer to the same index")
|
||||
+ self.index_no = 0
|
||||
+ self.key = [""]
|
||||
self.offset = 0
|
||||
- self.limit = limit
|
||||
+ self.limit = 0xffffffff
|
||||
|
||||
def pack(self):
|
||||
buf = ctypes.create_string_buffer(PACKET_BUF_LEN)
|
||||
@@ -266,10 +260,8 @@
|
||||
self.index_no,
|
||||
self.offset,
|
||||
self.limit,
|
||||
- len(self.key_list))
|
||||
- offset = SELECT_REQUEST_FIXED_LEN
|
||||
- for key in self.key_list:
|
||||
- (buf, offset) = pack_tuple([key], buf, offset)
|
||||
+ 1)
|
||||
+ (buf, offset) = pack_tuple(self.key, buf, SELECT_REQUEST_FIXED_LEN)
|
||||
|
||||
return buf[:offset]
|
||||
|
158
databases/tarantool/files/patch-test_lib_tarantool_connection.py
Normal file
158
databases/tarantool/files/patch-test_lib_tarantool_connection.py
Normal file
|
@ -0,0 +1,158 @@
|
|||
--- test/lib/tarantool_connection.py.orig 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ test/lib/tarantool_connection.py 2011-12-13 00:23:04.673107891 +0000
|
||||
@@ -0,0 +1,155 @@
|
||||
+__author__ = "Konstantin Osipov <kostja.osipov@gmail.com>"
|
||||
+
|
||||
+# Redistribution and use in source and binary forms, with or without
|
||||
+# modification, are permitted provided that the following conditions
|
||||
+# are met:
|
||||
+# 1. Redistributions of source code must retain the above copyright
|
||||
+# notice, this list of conditions and the following disclaimer.
|
||||
+# 2. Redistributions in binary form must reproduce the above copyright
|
||||
+# notice, this list of conditions and the following disclaimer in the
|
||||
+# documentation and/or other materials provided with the distribution.
|
||||
+#
|
||||
+# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+# SUCH DAMAGE.
|
||||
+
|
||||
+import socket
|
||||
+import sys
|
||||
+import string
|
||||
+import cStringIO
|
||||
+import yaml
|
||||
+import re
|
||||
+import sql
|
||||
+import struct
|
||||
+import errno
|
||||
+
|
||||
+is_admin_re = re.compile("^\s*(show|save|exec|exit|reload|help)", re.I)
|
||||
+
|
||||
+class AdminConnection:
|
||||
+ def __init__(self, host, port):
|
||||
+ self.host = host
|
||||
+ self.port = port
|
||||
+ self.is_connected = False
|
||||
+ self.stream = cStringIO.StringIO()
|
||||
+
|
||||
+ def connect(self):
|
||||
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
+ self.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
|
||||
+ self.socket.connect((self.host, self.port))
|
||||
+ self.is_connected = True
|
||||
+
|
||||
+ def disconnect(self):
|
||||
+ if self.is_connected:
|
||||
+ self.socket.close()
|
||||
+ self.is_connected = False
|
||||
+
|
||||
+ def reconnect(self):
|
||||
+ self.disconnect()
|
||||
+ self.connect()
|
||||
+
|
||||
+ def opt_reconnect(self):
|
||||
+ """ On a socket which was disconnected, recv of 0 bytes immediately
|
||||
+ returns with no data. On a socket which is alive, it returns EAGAIN.
|
||||
+ Make use of this property and detect whether or not the socket is
|
||||
+ dead. Reconnect a dead socket, do nothing if the socket is good."""
|
||||
+ try:
|
||||
+ if self.socket.recv(0, socket.MSG_DONTWAIT) == '':
|
||||
+ self.reconnect()
|
||||
+ except socket.error as e:
|
||||
+ if e.errno == errno.EAGAIN:
|
||||
+ pass
|
||||
+ else:
|
||||
+ self.reconnect()
|
||||
+
|
||||
+ def execute(self, command):
|
||||
+ self.opt_reconnect()
|
||||
+ return self.execute_no_reconnect(command)
|
||||
+
|
||||
+ def execute_no_reconnect(self, command):
|
||||
+ self.socket.sendall(command)
|
||||
+
|
||||
+ bufsiz = 4096
|
||||
+ res = ""
|
||||
+
|
||||
+ while True:
|
||||
+ buf = self.socket.recv(bufsiz)
|
||||
+ if not buf:
|
||||
+ break
|
||||
+ res = res + buf;
|
||||
+ if (res.rfind("\r\n...\r\n") >= 0):
|
||||
+ break
|
||||
+
|
||||
+ # validate yaml by parsing it
|
||||
+ yaml.load(res)
|
||||
+
|
||||
+ return res
|
||||
+
|
||||
+ def write(self, fragment):
|
||||
+ """This is to support print >> admin, "command" syntax.
|
||||
+ For every print statement, write is invoked twice: one to
|
||||
+ write the command itself, and another to write \n. We should
|
||||
+ accumulate all writes until we receive \n. When we receive it,
|
||||
+ we execute the command, and rewind the stream."""
|
||||
+
|
||||
+ newline_pos = fragment.rfind("\n")
|
||||
+ while newline_pos >= 0:
|
||||
+ self.stream.write(fragment[:newline_pos+1])
|
||||
+ statement = self.stream.getvalue()
|
||||
+ sys.stdout.write(statement)
|
||||
+ sys.stdout.write(self.execute(statement))
|
||||
+ fragment = fragment[newline_pos+1:]
|
||||
+ newline_pos = fragment.rfind("\n")
|
||||
+ self.stream.seek(0)
|
||||
+ self.stream.truncate()
|
||||
+
|
||||
+ self.stream.write(fragment)
|
||||
+
|
||||
+ def __enter__(self):
|
||||
+ self.connect()
|
||||
+ return self
|
||||
+
|
||||
+ def __exit__(self, type, value, tb):
|
||||
+ self.disconnect()
|
||||
+
|
||||
+class DataConnection(AdminConnection):
|
||||
+
|
||||
+ def recvall(self, length):
|
||||
+ res = ""
|
||||
+ while len(res) < length:
|
||||
+ buf = self.socket.recv(length - len(res))
|
||||
+ res = res + buf
|
||||
+ return res
|
||||
+
|
||||
+ def execute_no_reconnect(self, command):
|
||||
+ statement = sql.parse("sql", command)
|
||||
+ if statement == None:
|
||||
+ return "You have an error in your SQL syntax\n"
|
||||
+
|
||||
+ payload = statement.pack()
|
||||
+ header = struct.pack("<lll", statement.reqeust_type, len(payload), 0)
|
||||
+
|
||||
+ self.socket.sendall(header)
|
||||
+ if len(payload):
|
||||
+ self.socket.sendall(payload)
|
||||
+
|
||||
+ IPROTO_HEADER_SIZE = 12
|
||||
+
|
||||
+ header = self.recvall(IPROTO_HEADER_SIZE)
|
||||
+
|
||||
+ response_len = struct.unpack("<lll", header)[1]
|
||||
+
|
||||
+ if response_len:
|
||||
+ response = self.recvall(response_len)
|
||||
+ else:
|
||||
+ response = None
|
||||
+
|
||||
+ return statement.unpack(response) + "\n"
|
||||
+
|
|
@ -0,0 +1,266 @@
|
|||
--- test/lib/tarantool_silverbox_server.py.orig 2011-05-14 12:16:32.000000000 +0000
|
||||
+++ test/lib/tarantool_silverbox_server.py 2011-12-13 00:23:04.673107891 +0000
|
||||
@@ -1,35 +1,234 @@
|
||||
+import os
|
||||
+import stat
|
||||
import shutil
|
||||
import subprocess
|
||||
-import yaml
|
||||
-import ConfigParser
|
||||
-from tarantool_server import TarantoolServer, TarantoolConfigFile
|
||||
-from tarantool_admin import TarantoolAdmin
|
||||
-from silverbox import Silverbox
|
||||
-
|
||||
-class TarantoolSilverboxServer(TarantoolServer):
|
||||
- def __new__(cls, core="tarantool", module="silverbox"):
|
||||
- return TarantoolServer.__new__(cls)
|
||||
-
|
||||
- def __init__(self, core="tarantool", module="silverbox"):
|
||||
- TarantoolServer.__init__(self, core, module)
|
||||
-
|
||||
- def configure(self, config):
|
||||
- TarantoolServer.configure(self, config)
|
||||
- with open(self.config) as fp:
|
||||
- dummy_section_name = "tarantool"
|
||||
- config = ConfigParser.ConfigParser()
|
||||
- config.readfp(TarantoolConfigFile(fp, dummy_section_name))
|
||||
- self.primary_port = int(config.get(dummy_section_name, "primary_port"))
|
||||
- self.admin_port = int(config.get(dummy_section_name, "admin_port"))
|
||||
- self.port = self.admin_port
|
||||
- self.admin = TarantoolAdmin("localhost", self.admin_port)
|
||||
- self.sql = Silverbox("localhost", self.primary_port)
|
||||
-
|
||||
- def init(self):
|
||||
-# init storage
|
||||
- subprocess.check_call([self.binary, "--init_storage"],
|
||||
- cwd = self.vardir,
|
||||
+import pexpect
|
||||
+import sys
|
||||
+import signal
|
||||
+import time
|
||||
+import socket
|
||||
+import daemon
|
||||
+import glob
|
||||
+
|
||||
+def wait_until_connected(host, port):
|
||||
+ """Wait until the server is started and accepting connections"""
|
||||
+ is_connected = False
|
||||
+ while not is_connected:
|
||||
+ try:
|
||||
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
+ sock.connect((host, port))
|
||||
+ is_connected = True
|
||||
+ sock.close()
|
||||
+ except socket.error as e:
|
||||
+ time.sleep(0.001)
|
||||
+
|
||||
+
|
||||
+def prepare_gdb(args):
|
||||
+ """Prepare server startup arguments to run under gdb."""
|
||||
+ if "TERM" in os.environ:
|
||||
+ term = os.environ["TERM"]
|
||||
+ else:
|
||||
+ term = "xterm"
|
||||
+
|
||||
+ if term not in ["xterm", "rxvt", "urxvt", "gnome-terminal", "konsole"]:
|
||||
+ raise RuntimeError("--gdb: unsupported terminal {0}".format(term))
|
||||
+
|
||||
+ args = [ term, "-e ", "gdb", "-ex", "break main", "-ex", "run"] + args
|
||||
+ return args
|
||||
+
|
||||
+
|
||||
+def prepare_valgrind(args, valgrind_opts):
|
||||
+ "Prepare server startup arguments to run under valgrind."
|
||||
+ args = ([ "valgrind", "--log-file=valgrind.log", "--quiet" ] +
|
||||
+ valgrind_opts.split(" ") + args)
|
||||
+ return args
|
||||
+
|
||||
+
|
||||
+def check_tmpfs_exists():
|
||||
+ return os.uname()[0] in 'Linux' and os.path.isdir("/dev/shm")
|
||||
+
|
||||
+def create_tmpfs_vardir(vardir):
|
||||
+ os.mkdir(os.path.join("/dev/shm", vardir))
|
||||
+ os.symlink(os.path.join("/dev/shm", vardir), vardir)
|
||||
+
|
||||
+class TarantoolSilverboxServer:
|
||||
+ """Server represents a single server instance. Normally, the
|
||||
+ program operates with only one server, but in future we may add
|
||||
+ replication slaves. The server is started once at the beginning
|
||||
+ of each suite, and stopped at the end."""
|
||||
+
|
||||
+ def __init__(self, args, suite_ini):
|
||||
+ """Set server options: path to configuration file, pid file, exe, etc."""
|
||||
+ self.args = args
|
||||
+ self.suite_ini = suite_ini
|
||||
+ self.path_to_pidfile = os.path.join(args.vardir, suite_ini["pidfile"])
|
||||
+ self.path_to_exe = None
|
||||
+ self.abspath_to_exe = None
|
||||
+ self.is_started = False
|
||||
+
|
||||
+ def install(self, silent = False):
|
||||
+ """Start server instance: check if the old one exists, kill it
|
||||
+ if necessary, create necessary directories and files, start
|
||||
+ the server. The server working directory is taken from 'vardir',
|
||||
+ specified in the prgoram options.
|
||||
+ Currently this is implemented for tarantool_silverbox only."""
|
||||
+
|
||||
+ vardir = self.args.vardir
|
||||
+
|
||||
+ if not silent:
|
||||
+ print "Installing the server..."
|
||||
+
|
||||
+ if self.path_to_exe == None:
|
||||
+ self.path_to_exe = self.find_exe()
|
||||
+ self.abspath_to_exe = os.path.abspath(self.path_to_exe)
|
||||
+
|
||||
+ if not silent:
|
||||
+ print " Found executable at " + self.path_to_exe + "."
|
||||
+
|
||||
+ if not silent:
|
||||
+ print " Creating and populating working directory in " +\
|
||||
+ vardir + "..."
|
||||
+
|
||||
+ if os.access(vardir, os.F_OK):
|
||||
+ if not silent:
|
||||
+ print " Found old vardir, deleting..."
|
||||
+ self.kill_old_server()
|
||||
+ for filename in (glob.glob(os.path.join(vardir, "*.snap")) +
|
||||
+ glob.glob(os.path.join(vardir, "*.inprogress")) +
|
||||
+ glob.glob(os.path.join(vardir, "*.xlog")) +
|
||||
+ glob.glob(os.path.join(vardir, "*.cfg")) +
|
||||
+ glob.glob(os.path.join(vardir, "*.log")) +
|
||||
+ glob.glob(os.path.join(vardir, "*.core.*")) +
|
||||
+ glob.glob(os.path.join(vardir, "core"))):
|
||||
+ os.remove(filename)
|
||||
+ else:
|
||||
+ if (self.args.mem == True and check_tmpfs_exists() and
|
||||
+ os.path.basename(vardir) == vardir):
|
||||
+ create_tmpfs_vardir(vardir)
|
||||
+ else:
|
||||
+ os.mkdir(vardir)
|
||||
+
|
||||
+ shutil.copy(self.suite_ini["config"], self.args.vardir)
|
||||
+
|
||||
+ subprocess.check_call([self.abspath_to_exe, "--init_storage"],
|
||||
+ cwd = self.args.vardir,
|
||||
# catch stdout/stderr to not clutter output
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE)
|
||||
|
||||
+ p = subprocess.Popen([self.abspath_to_exe, "--version"],
|
||||
+ cwd = self.args.vardir,
|
||||
+ stdout = subprocess.PIPE)
|
||||
+ version = p.stdout.read().rstrip()
|
||||
+ p.wait()
|
||||
+
|
||||
+ if not silent:
|
||||
+ print "Starting {0} {1}.".format(os.path.basename(self.abspath_to_exe),
|
||||
+ version)
|
||||
+
|
||||
+ def start(self, silent = False):
|
||||
+
|
||||
+ if self.is_started:
|
||||
+ if not silent:
|
||||
+ print "The server is already started."
|
||||
+ return
|
||||
+
|
||||
+ if not silent:
|
||||
+ print "Starting the server..."
|
||||
+
|
||||
+ args = [self.abspath_to_exe]
|
||||
+
|
||||
+ if (self.args.start_and_exit and
|
||||
+ not self.args.valgrind and not self.args.gdb):
|
||||
+ args.append("--daemonize")
|
||||
+ if self.args.gdb:
|
||||
+ args = prepare_gdb(args)
|
||||
+ elif self.args.valgrind:
|
||||
+ args = prepare_valgrind(args, self.args.valgrind_opts)
|
||||
+
|
||||
+ if self.args.start_and_exit and self.args.valgrind:
|
||||
+ pid = os.fork()
|
||||
+ if pid > 0:
|
||||
+ os.wait()
|
||||
+ else:
|
||||
+ with daemon.DaemonContext(working_directory = self.args.vardir):
|
||||
+ os.execvp(args[0], args)
|
||||
+ else:
|
||||
+ self.server = pexpect.spawn(args[0], args[1:], cwd = self.args.vardir)
|
||||
+ if self.args.start_and_exit:
|
||||
+ self.server.wait()
|
||||
+
|
||||
+# wait until the server is connectedk
|
||||
+ if self.args.gdb and self.args.start_and_exit:
|
||||
+ time.sleep(1)
|
||||
+ elif not self.args.start_and_exit and not self.args.gdb:
|
||||
+ self.server.expect_exact("entering event loop")
|
||||
+ else:
|
||||
+ wait_until_connected(self.suite_ini["host"], self.suite_ini["port"])
|
||||
+
|
||||
+# Set is_started flag, to nicely support cleanup during an exception.
|
||||
+ self.is_started = True
|
||||
+
|
||||
+
|
||||
+ def stop(self, silent = False):
|
||||
+ """Stop server instance. Do nothing if the server is not started,
|
||||
+ to properly shut down the server in case of an exception during
|
||||
+ start up."""
|
||||
+ if self.is_started:
|
||||
+ if not silent:
|
||||
+ print "Stopping the server..."
|
||||
+ if self.args.gdb:
|
||||
+ self.kill_old_server(True)
|
||||
+ self.server.terminate()
|
||||
+ self.server.expect(pexpect.EOF)
|
||||
+ self.is_started = False
|
||||
+ elif not silent:
|
||||
+ print "The server is not started."
|
||||
+
|
||||
+ def restart(self):
|
||||
+ self.stop(True)
|
||||
+ self.start(True)
|
||||
+
|
||||
+ def test_option(self, option_list_str):
|
||||
+ args = [self.abspath_to_exe] + option_list_str.split()
|
||||
+ print " ".join([os.path.basename(self.abspath_to_exe)] + args[1:])
|
||||
+ output = subprocess.Popen(args,
|
||||
+ cwd = self.args.vardir,
|
||||
+ stdout = subprocess.PIPE,
|
||||
+ stderr = subprocess.STDOUT).stdout.read()
|
||||
+ print output
|
||||
+
|
||||
+
|
||||
+ def find_exe(self):
|
||||
+ """Locate server executable in the bindir. We just take
|
||||
+ the first thing looking like an exe in there."""
|
||||
+
|
||||
+ print " Looking for server binary in {0}...".format(self.args.bindir)
|
||||
+ if (os.access(self.args.bindir, os.F_OK) == False or
|
||||
+ stat.S_ISDIR(os.stat(self.args.bindir).st_mode) == False):
|
||||
+ raise RuntimeError("Directory " + self.args.bindir + " doesn't exist")
|
||||
+
|
||||
+ for f in os.listdir(self.args.bindir):
|
||||
+ f = os.path.join(self.args.bindir, f)
|
||||
+ st_mode = os.stat(f).st_mode
|
||||
+ if stat.S_ISREG(st_mode) and st_mode & stat.S_IXUSR:
|
||||
+ return f
|
||||
+
|
||||
+ raise RuntimeError("Can't find server executable in " + self.args.bindir)
|
||||
+
|
||||
+ def kill_old_server(self, silent = False):
|
||||
+ """Kill old server instance if it exists."""
|
||||
+ if os.access(self.path_to_pidfile, os.F_OK) == False:
|
||||
+ return # Nothing to do
|
||||
+ pid = 0
|
||||
+ with open(self.path_to_pidfile) as f:
|
||||
+ pid = int(f.read())
|
||||
+ if not silent:
|
||||
+ print " Found old server, pid {0}, killing...".format(pid)
|
||||
+ try:
|
||||
+ os.kill(pid, signal.SIGTERM)
|
||||
+ while os.kill(pid, 0) != -1:
|
||||
+ time.sleep(0.001)
|
||||
+ except OSError:
|
||||
+ pass
|
||||
+
|
210
databases/tarantool/files/patch-test_lib_test_suite.py
Normal file
210
databases/tarantool/files/patch-test_lib_test_suite.py
Normal file
|
@ -0,0 +1,210 @@
|
|||
--- test/lib/test_suite.py.orig 2011-05-14 12:16:32.000000000 +0000
|
||||
+++ test/lib/test_suite.py 2011-12-13 00:23:04.673107891 +0000
|
||||
@@ -10,13 +10,21 @@
|
||||
import filecmp
|
||||
import shlex
|
||||
import time
|
||||
-from server import Server
|
||||
+from tarantool_silverbox_server import TarantoolSilverboxServer
|
||||
+from tarantool_connection import AdminConnection, DataConnection
|
||||
import tarantool_preprocessor
|
||||
import re
|
||||
import cStringIO
|
||||
import string
|
||||
import traceback
|
||||
|
||||
+class TestRunException(RuntimeError):
|
||||
+ """A common exception to use across the program."""
|
||||
+ def __init__(self, message):
|
||||
+ self.message = message
|
||||
+ def __str__(self):
|
||||
+ return self.message
|
||||
+
|
||||
class FilteredStream:
|
||||
"""Helper class to filter .result file output"""
|
||||
def __init__(self, filename):
|
||||
@@ -66,12 +74,12 @@
|
||||
"""Initialize test properties: path to test file, path to
|
||||
temporary result file, path to the client program, test status."""
|
||||
self.name = name
|
||||
- self.args = args
|
||||
- self.suite_ini = suite_ini
|
||||
self.result = name.replace(".test", ".result")
|
||||
- self.tmp_result = os.path.join(self.args.vardir,
|
||||
+ self.tmp_result = os.path.join(suite_ini["vardir"],
|
||||
os.path.basename(self.result))
|
||||
self.reject = name.replace(".test", ".reject")
|
||||
+ self.args = args
|
||||
+ self.suite_ini = suite_ini
|
||||
self.is_executed = False
|
||||
self.is_executed_ok = None
|
||||
self.is_equal_result = None
|
||||
@@ -81,7 +89,7 @@
|
||||
"""Return true if this test was run successfully."""
|
||||
return self.is_executed and self.is_executed_ok and self.is_equal_result
|
||||
|
||||
- def run(self, server):
|
||||
+ def run(self):
|
||||
"""Execute the test assuming it's a python program.
|
||||
If the test aborts, print its output to stdout, and raise
|
||||
an exception. Else, comprare result and reject files.
|
||||
@@ -91,10 +99,18 @@
|
||||
|
||||
diagnostics = "unknown"
|
||||
save_stdout = sys.stdout
|
||||
+ admin = AdminConnection(self.suite_ini["host"],
|
||||
+ self.suite_ini["admin_port"])
|
||||
+ sql = DataConnection(self.suite_ini["host"],
|
||||
+ self.suite_ini["port"])
|
||||
+ server = self.suite_ini["server"]
|
||||
try:
|
||||
+ admin.connect()
|
||||
+ sql.connect()
|
||||
sys.stdout = FilteredStream(self.tmp_result)
|
||||
- stdout_fileno = sys.stdout.stream.fileno()
|
||||
- execfile(self.name, dict(locals(), **server.__dict__))
|
||||
+ server = self.suite_ini["server"]
|
||||
+ vardir = self.suite_ini["vardir"]
|
||||
+ execfile(self.name, globals(), locals())
|
||||
self.is_executed_ok = True
|
||||
except Exception as e:
|
||||
traceback.print_exc(e)
|
||||
@@ -103,6 +119,8 @@
|
||||
if sys.stdout and sys.stdout != save_stdout:
|
||||
sys.stdout.close()
|
||||
sys.stdout = save_stdout;
|
||||
+ admin.disconnect()
|
||||
+ sql.disconnect()
|
||||
|
||||
self.is_executed = True
|
||||
|
||||
@@ -111,7 +129,7 @@
|
||||
|
||||
if self.args.valgrind:
|
||||
self.is_valgrind_clean = \
|
||||
- check_valgrind_log(server.valgrind_log) == False
|
||||
+ check_valgrind_log(self.suite_ini["valgrind_log"]) == False
|
||||
|
||||
if self.is_executed_ok and self.is_equal_result and self.is_valgrind_clean:
|
||||
print "[ pass ]"
|
||||
@@ -133,12 +151,12 @@
|
||||
where = ": wrong test output"
|
||||
elif not self.is_valgrind_clean:
|
||||
os.remove(self.reject)
|
||||
- self.print_diagnostics(server.valgrind_log,
|
||||
+ self.print_diagnostics(self.suite_ini["valgrind_log"],
|
||||
"Test failed! Last 10 lines of valgrind.log:")
|
||||
where = ": there were warnings in valgrind.log"
|
||||
|
||||
- if not self.args.is_force:
|
||||
- raise RuntimeError("Failed to run test " + self.name + where)
|
||||
+ if not self.suite_ini["is_force"]:
|
||||
+ raise TestRunException("Failed to run test " + self.name + where)
|
||||
|
||||
|
||||
def print_diagnostics(self, logfile, message):
|
||||
@@ -167,6 +185,20 @@
|
||||
for line in diff:
|
||||
sys.stdout.write(line)
|
||||
|
||||
+class TarantoolConfigFile:
|
||||
+ """ConfigParser can't read files without sections, work it around"""
|
||||
+ def __init__(self, fp, section_name):
|
||||
+ self.fp = fp
|
||||
+ self.section_name = "[" + section_name + "]"
|
||||
+ def readline(self):
|
||||
+ if self.section_name:
|
||||
+ section_name = self.section_name
|
||||
+ self.section_name = None
|
||||
+ return section_name
|
||||
+ # tarantool.cfg puts string values in quote
|
||||
+ return self.fp.readline().replace("\"", '')
|
||||
+
|
||||
+
|
||||
class TestSuite:
|
||||
"""Each test suite contains a number of related tests files,
|
||||
located in the same directory on disk. Each test file has
|
||||
@@ -186,13 +218,15 @@
|
||||
self.args = args
|
||||
self.tests = []
|
||||
self.ini = {}
|
||||
-
|
||||
- self.ini["core"] = "tarantool"
|
||||
- self.ini["module"] = "silverbox"
|
||||
+ self.ini["suite_path"] = suite_path
|
||||
+ self.ini["host"] = "localhost"
|
||||
+ self.ini["is_force"] = self.args.is_force
|
||||
+ self.ini["vardir"] = args.vardir
|
||||
+ self.ini["valgrind_log"] = os.path.join(args.vardir, "valgrind.log")
|
||||
|
||||
if os.access(suite_path, os.F_OK) == False:
|
||||
- raise RuntimeError("Suite \"" + suite_path +\
|
||||
- "\" doesn't exist")
|
||||
+ raise TestRunException("Suite \"" + suite_path +\
|
||||
+ "\" doesn't exist")
|
||||
|
||||
# read the suite config
|
||||
config = ConfigParser.ConfigParser()
|
||||
@@ -203,6 +237,16 @@
|
||||
self.ini["disabled"] = dict.fromkeys(self.ini["disabled"].split(" "))
|
||||
else:
|
||||
self.ini["disabled"] = dict()
|
||||
+# import the necessary module for test suite client
|
||||
+
|
||||
+# now read the server config, we need some properties from it
|
||||
+
|
||||
+ with open(self.ini["config"]) as fp:
|
||||
+ dummy_section_name = "tarantool_silverbox"
|
||||
+ config.readfp(TarantoolConfigFile(fp, dummy_section_name))
|
||||
+ self.ini["pidfile"] = config.get(dummy_section_name, "pid_file")
|
||||
+ self.ini["admin_port"] = int(config.get(dummy_section_name, "admin_port"))
|
||||
+ self.ini["port"] = int(config.get(dummy_section_name, "primary_port"))
|
||||
|
||||
print "Collecting tests in \"" + suite_path + "\": " +\
|
||||
self.ini["description"] + "."
|
||||
@@ -216,17 +260,9 @@
|
||||
def run_all(self):
|
||||
"""For each file in the test suite, run client program
|
||||
assuming each file represents an individual test."""
|
||||
- try:
|
||||
- server = Server(self.ini["core"], self.ini["module"])
|
||||
- except Exception as e:
|
||||
- print e
|
||||
- raise RuntimeError("Unknown server: core = {0}, module = {1}".format(
|
||||
- self.ini["core"], self.ini["module"]))
|
||||
- server.deploy(self.ini["config"],
|
||||
- server.find_exe(self.args.builddir, silent=False),
|
||||
- self.args.vardir,
|
||||
- self.args.mem, self.args.start_and_exit, self.args.gdb, self.args.valgrind,
|
||||
- silent=False)
|
||||
+ server = TarantoolSilverboxServer(self.args, self.ini)
|
||||
+ server.install()
|
||||
+ server.start()
|
||||
if self.args.start_and_exit:
|
||||
print " Start and exit requested, exiting..."
|
||||
exit(0)
|
||||
@@ -247,7 +283,7 @@
|
||||
if os.path.basename(test.name) in self.ini["disabled"]:
|
||||
print "[ skip ]"
|
||||
else:
|
||||
- test.run(server)
|
||||
+ test.run()
|
||||
if not test.passed():
|
||||
failed_tests.append(test.name)
|
||||
|
||||
@@ -255,11 +291,9 @@
|
||||
if len(failed_tests):
|
||||
print "Failed {0} tests: {1}.".format(len(failed_tests),
|
||||
", ".join(failed_tests))
|
||||
- server.stop(silent=False)
|
||||
- server.cleanup()
|
||||
+ server.stop();
|
||||
|
||||
- if self.args.valgrind and check_valgrind_log(server.valgrind_log):
|
||||
+ if self.args.valgrind and check_valgrind_log(self.ini["valgrind_log"]):
|
||||
print " Error! There were warnings/errors in valgrind log file:"
|
||||
- print_tail_n(server.valgrind_log, 20)
|
||||
- return 1
|
||||
- return len(failed_tests)
|
||||
+ print_tail_n(self.ini["valgrind_log"], 20)
|
||||
+
|
30
databases/tarantool/files/patch-test_tarantool
Normal file
30
databases/tarantool/files/patch-test_tarantool
Normal file
|
@ -0,0 +1,30 @@
|
|||
--- test/tarantool.orig 2011-05-14 12:16:32.000000000 +0000
|
||||
+++ test/tarantool 2011-12-13 01:12:12.696699437 +0000
|
||||
@@ -1,4 +1,4 @@
|
||||
-#! /usr/bin/python
|
||||
+#! /usr/bin/env python
|
||||
"""A simplistic client for tarantool/silverbox: administrative
|
||||
console and SQL client.
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
import socket
|
||||
import sys
|
||||
import string
|
||||
-from lib.tarantool_admin import TarantoolAdmin, is_admin_re
|
||||
-from lib.box import Box
|
||||
+from lib.tarantool_connection import AdminConnection, DataConnection, \
|
||||
+ is_admin_re
|
||||
|
||||
class Options:
|
||||
def __init__(self):
|
||||
@@ -94,8 +94,8 @@
|
||||
def main():
|
||||
init_readline_history()
|
||||
options = Options()
|
||||
- admin_con = TarantoolAdmin(options.args.host, options.args.admin_port)
|
||||
- data_con = Box(options.args.host, options.args.port)
|
||||
+ admin_con = AdminConnection(options.args.host, options.args.admin_port)
|
||||
+ data_con = DataConnection(options.args.host, options.args.port)
|
||||
try:
|
||||
admin_con.connect()
|
||||
data_con.connect()
|
10
databases/tarantool/files/pkg-message.in
Normal file
10
databases/tarantool/files/pkg-message.in
Normal file
|
@ -0,0 +1,10 @@
|
|||
#########################################################
|
||||
#
|
||||
#
|
||||
# After install you'll need init storage:
|
||||
#
|
||||
# %%PREFIX%%/bin/tarantool_silverbox --init-storage \
|
||||
# -c %%ETCDIR%%/tarantool.cfg
|
||||
#
|
||||
#
|
||||
#########################################################
|
29
databases/tarantool/files/tarantool.in
Normal file
29
databases/tarantool/files/tarantool.in
Normal file
|
@ -0,0 +1,29 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# PROVIDE: tarantool
|
||||
# REQUIRE: LOGIN
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
# tarantool_enable="YES"
|
||||
# tarantool_config=""
|
||||
#
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="tarantool"
|
||||
|
||||
tarantool_enable=${tarantool_enable:-"NO"}
|
||||
tarantool_config=${tarantool_config:-"%%ETCDIR%%/$name.cfg"}
|
||||
|
||||
rcvar=`set_rcvar`
|
||||
|
||||
load_rc_config "$name"
|
||||
|
||||
command="%%PREFIX%%/bin/tarantool_silverbox"
|
||||
command_args="--daemonize --config ${tarantool_config}"
|
||||
pidfile="/var/run/$name.pid"
|
||||
|
||||
run_rc_command "$1"
|
||||
|
5
databases/tarantool/pkg-descr
Normal file
5
databases/tarantool/pkg-descr
Normal file
|
@ -0,0 +1,5 @@
|
|||
Tarantool/Box, or simply Tarantool, is a high performance key/value
|
||||
storage server. The code is available for free under the terms of
|
||||
BSD license. Supported platforms are GNU/Linux and FreeBSD.
|
||||
|
||||
WWW: http://tarantool.org/
|
21
databases/tarantool/pkg-plist
Normal file
21
databases/tarantool/pkg-plist
Normal file
|
@ -0,0 +1,21 @@
|
|||
bin/lib/__init__.py
|
||||
bin/lib/sql.g
|
||||
bin/lib/sql.py
|
||||
bin/lib/sql_ast.py
|
||||
bin/lib/tarantool_connection.py
|
||||
bin/lib/tarantool_preprocessor.py
|
||||
bin/lib/tarantool_silverbox_server.py
|
||||
bin/lib/test_suite.py
|
||||
bin/lib/yapps/__init__.py
|
||||
bin/lib/yapps/runtime.py
|
||||
bin/tarantool
|
||||
bin/tarantool_feeder
|
||||
bin/tarantool_silverbox
|
||||
%%DOCSDIR%%/LICENSE
|
||||
%%DOCSDIR%%/README
|
||||
%%DOCSDIR%%/silverbox-protocol.txt
|
||||
%%ETCDIR%%/tarantool.cfg
|
||||
@dirrm %%DOCSDIR%%
|
||||
@dirrm %%ETCDIR%%
|
||||
@dirrm bin/lib/yapps
|
||||
@dirrm bin/lib
|
Loading…
Reference in a new issue