blob: c084a2e02972e8fbf9232e1265b86dd5bc1fee50 [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import ctypes
import os
import platform
from ctypes import (
CFUNCTYPE,
POINTER,
Structure,
c_char_p,
c_float,
c_int,
c_int64,
c_size_t,
c_uint8,
c_uint32,
c_uint64,
c_void_p,
)
def _lib_name():
system = platform.system()
if system == "Darwin":
return "libpaimon_vindex_ffi.dylib"
if system == "Windows":
return "paimon_vindex_ffi.dll"
return "libpaimon_vindex_ffi.so"
def _load_library():
lib_name = _lib_name()
search_paths = []
env_path = os.environ.get("PAIMON_VINDEX_LIB_PATH")
if env_path:
if os.path.isfile(env_path):
return ctypes.CDLL(env_path)
search_paths.append(env_path)
pkg_dir = os.path.dirname(os.path.abspath(__file__))
search_paths.append(pkg_dir)
search_paths.append(os.path.join(pkg_dir, "..", ".."))
for rel in [
os.path.join("..", "..", "target", "release"),
os.path.join("..", "..", "target", "debug"),
os.path.join("..", "..", "..", "target", "release"),
os.path.join("..", "..", "..", "target", "debug"),
]:
search_paths.append(os.path.join(pkg_dir, rel))
for directory in search_paths:
candidate = os.path.abspath(os.path.join(directory, lib_name))
if os.path.isfile(candidate):
return ctypes.CDLL(candidate)
try:
return ctypes.CDLL(lib_name)
except OSError as exc:
raise OSError(
f"Cannot find {lib_name}. Build the native library first with "
"'cargo build --release -p paimon-vindex-ffi', or set "
"PAIMON_VINDEX_LIB_PATH to the directory containing it."
) from exc
lib = _load_library()
WRITE_FN = CFUNCTYPE(c_int, c_void_p, POINTER(c_uint8), c_size_t)
FLUSH_FN = CFUNCTYPE(c_int, c_void_p)
GET_POS_FN = CFUNCTYPE(c_int64, c_void_p)
READ_AT_FN = CFUNCTYPE(c_int, c_void_p, c_uint64, POINTER(c_uint8), c_size_t)
class PaimonVindexOutputFile(Structure):
_fields_ = [
("ctx", c_void_p),
("write_fn", WRITE_FN),
("flush_fn", FLUSH_FN),
("get_pos_fn", GET_POS_FN),
]
class PaimonVindexInputFile(Structure):
_fields_ = [
("ctx", c_void_p),
("read_at_fn", READ_AT_FN),
]
class PaimonVindexMetadata(Structure):
_fields_ = [
("index_type", c_uint32),
("dimension", c_size_t),
("nlist", c_size_t),
("metric", c_uint32),
("total_vectors", c_int64),
("pq_m", c_size_t),
("hnsw_m", c_size_t),
("hnsw_ef_construction", c_size_t),
("hnsw_max_level", c_size_t),
]
class PaimonVindexSearchParams(Structure):
_fields_ = [
("top_k", c_size_t),
("nprobe", c_size_t),
("ef_search", c_size_t),
("query_bits", c_size_t),
]
lib.paimon_vindex_last_error.argtypes = []
lib.paimon_vindex_last_error.restype = c_char_p
lib.paimon_vindex_trainer_open.argtypes = [
POINTER(c_char_p),
POINTER(c_char_p),
c_size_t,
]
lib.paimon_vindex_trainer_open.restype = c_void_p
lib.paimon_vindex_trainer_free.argtypes = [c_void_p]
lib.paimon_vindex_trainer_free.restype = None
lib.paimon_vindex_trainer_dimension.argtypes = [c_void_p, POINTER(c_size_t)]
lib.paimon_vindex_trainer_dimension.restype = c_int
lib.paimon_vindex_trainer_add_training_vectors.argtypes = [
c_void_p,
POINTER(c_float),
c_size_t,
]
lib.paimon_vindex_trainer_add_training_vectors.restype = c_int
lib.paimon_vindex_trainer_finish.argtypes = [c_void_p]
lib.paimon_vindex_trainer_finish.restype = c_void_p
lib.paimon_vindex_training_free.argtypes = [c_void_p]
lib.paimon_vindex_training_free.restype = None
lib.paimon_vindex_writer_open.argtypes = [c_void_p]
lib.paimon_vindex_writer_open.restype = c_void_p
lib.paimon_vindex_writer_free.argtypes = [c_void_p]
lib.paimon_vindex_writer_free.restype = None
lib.paimon_vindex_writer_dimension.argtypes = [c_void_p, POINTER(c_size_t)]
lib.paimon_vindex_writer_dimension.restype = c_int
lib.paimon_vindex_writer_add_vectors.argtypes = [
c_void_p,
POINTER(c_int64),
POINTER(c_float),
c_size_t,
]
lib.paimon_vindex_writer_add_vectors.restype = c_int
lib.paimon_vindex_writer_write_index.argtypes = [
c_void_p,
PaimonVindexOutputFile,
]
lib.paimon_vindex_writer_write_index.restype = c_int
lib.paimon_vindex_reader_open.argtypes = [PaimonVindexInputFile]
lib.paimon_vindex_reader_open.restype = c_void_p
lib.paimon_vindex_reader_free.argtypes = [c_void_p]
lib.paimon_vindex_reader_free.restype = None
lib.paimon_vindex_reader_metadata.argtypes = [
c_void_p,
POINTER(PaimonVindexMetadata),
]
lib.paimon_vindex_reader_metadata.restype = c_int
lib.paimon_vindex_reader_optimize_for_search.argtypes = [c_void_p]
lib.paimon_vindex_reader_optimize_for_search.restype = c_int
lib.paimon_vindex_reader_search.argtypes = [
c_void_p,
POINTER(c_float),
PaimonVindexSearchParams,
POINTER(c_int64),
POINTER(c_float),
c_size_t,
]
lib.paimon_vindex_reader_search.restype = c_int
lib.paimon_vindex_reader_search_with_roaring_filter.argtypes = [
c_void_p,
POINTER(c_float),
PaimonVindexSearchParams,
POINTER(c_uint8),
c_size_t,
POINTER(c_int64),
POINTER(c_float),
c_size_t,
]
lib.paimon_vindex_reader_search_with_roaring_filter.restype = c_int
lib.paimon_vindex_reader_search_batch.argtypes = [
c_void_p,
POINTER(c_float),
c_size_t,
PaimonVindexSearchParams,
POINTER(c_int64),
POINTER(c_float),
c_size_t,
]
lib.paimon_vindex_reader_search_batch.restype = c_int
lib.paimon_vindex_reader_search_batch_with_roaring_filter.argtypes = [
c_void_p,
POINTER(c_float),
c_size_t,
PaimonVindexSearchParams,
POINTER(c_uint8),
c_size_t,
POINTER(c_int64),
POINTER(c_float),
c_size_t,
]
lib.paimon_vindex_reader_search_batch_with_roaring_filter.restype = c_int