1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00

the begginning

This commit is contained in:
david hill
2016-01-06 14:08:59 -06:00
parent 66a31debcb
commit f6afc42dd0
18251 changed files with 16460679 additions and 2 deletions

81
writeengine/shared/Makefile Executable file
View File

@ -0,0 +1,81 @@
include ../../rules.mak
include ../build/we_rules.mak
#******************************************************************************************
# $Id: Makefile 4589 2013-04-02 14:41:08Z rdempsey $
#
# Copyright (C) 2009-2013 Calpont Corporation
# All rights reserved
#*****************************************************************************************/
.PHONY: install clean docs test coverage leakcheck
SRCS=we_bulkrollbackmgr.cpp we_bulkrollbackfile.cpp we_bulkrollbackfilecompressed.cpp we_bulkrollbackfilecompressedhdfs.cpp we_fileop.cpp we_blockop.cpp we_dbfileop.cpp we_log.cpp we_simplesyslog.cpp we_convertor.cpp we_brm.cpp we_config.cpp we_cache.cpp we_stats.cpp we_define.cpp we_chunkmanager.cpp we_rbmetawriter.cpp we_dbrootextenttracker.cpp we_confirmhdfsdbfile.cpp
LINCLUDES=we_bulkrollbackmgr.h we_index.h we_define.h we_type.h we_fileop.h we_blockop.h we_dbfileop.h we_obj.h we_log.h we_simplesyslog.h we_convertor.h we_brm.h we_macro.h we_config.h we_cache.h we_stats.h we_typeext.h we_chunkmanager.h we_rbmetawriter.h we_dbrootextenttracker.h we_confirmhdfsdbfile.h
OBJS=$(SRCS:.cpp=.o)
object: $(OBJS)
mkdir -p $(LIBDIR)
cp *.o $(LIBDIR)
rm -f $(LIBDIR)/tshared.o
make install
install: bootstrap
bootstrap:
$(INSTALL) $(LINCLUDES) $(INSTALL_ROOT_INCLUDE)
clean:
rm -f $(LIBDIR)/tshared.o $(LIBDIR)/*gcov.o $(OBJS) tshared.o tshared core *~ *.tag *-gcov.* *.gcov tshared-gcov *.d *.swp *.dat *.txt *.log
for file in $(SRCS); do \
bfile=`basename $$file .cpp`; \
rm -f $(LIBDIR)/$${bfile}.o ; \
done
rm -rf html
docs:
doxygen $(EXPORT_ROOT)/etc/Doxyfile
tshared: $(OBJS) tshared.o
$(LINK.cpp) -o $@ $^ $(TLIBS)
test:
xtest: tshared object
$(IPCS_CLEANUP)
LD_LIBRARY_PATH=.:$(EXPORT_ROOT)/lib:/usr/local/lib ./tshared
%-gcov.o: %.cpp
$(COMPILE.cpp) -o $@ $^
cp *-gcov.o $(LIBDIR)
tshared-gcov: CXXFLAGS+=-fprofile-arcs -ftest-coverage
tshared-gcov: tshared-gcov.o $(subst .o,-gcov.o,$(OBJS))
$(LINK.cpp) -o $@ $^ $(GLIBS)
coverage:
xcoverage: tshared-gcov
$(IPCS_CLEANUP)
rm -f *.gcda
LD_LIBRARY_PATH=$(EXPORT_ROOT)/lib:/usr/local/lib ./tshared-gcov
for file in $(SRCS); do \
bfile=`basename $$file .cpp`; \
gcov -o $${bfile}-gcov $$file >/dev/null; \
done
/usr/local/bin/genCoverage.pl $(SRCS)
leakcheck:
xleakcheck: $(LIBRARY) tshared
$(IPCS_CLEANUP)
LD_LIBRARY_PATH=.:$(EXPORT_ROOT)/lib:/usr/local/lib valgrind --tool=memcheck --leak-check=yes ./tshared
%.d: %.cpp
@set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
ifndef BOOTSTRAP
-include $(SRCS:.cpp=.d) tshared.d
endif

View File

@ -0,0 +1,32 @@
# Copyright (C) 2014 InfiniDB, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; version 2 of
# the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
# $Id: Makefile.am 3720 2012-04-04 18:18:49Z rdempsey $
## Process this file with automake to produce Makefile.in
include_HEADERS = we_index.h we_define.h we_type.h we_fileop.h we_blockop.h we_dbfileop.h we_obj.h we_log.h we_simplesyslog.h we_convertor.h we_brm.h we_macro.h we_config.h we_cache.h we_stats.h we_bulkrollbackmgr.h we_typeext.h we_chunkmanager.h we_bulkrollbackfilecompressed.h we_bulkrollbackfilecompressedhdfs.h we_bulkrollbackfile.h we_rbmetawriter.h we_dbrootextenttracker.h we_confirmhdfsdbfile.h
test:
coverage:
leakcheck:
docs:
bootstrap: install-data-am

View File

@ -0,0 +1,454 @@
# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Copyright (C) 2014 InfiniDB, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; version 2 of
# the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
# $Id: Makefile.am 3720 2012-04-04 18:18:49Z rdempsey $
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = writeengine/shared
DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/compilerflags.m4 \
$(top_srcdir)/m4/functions.m4 $(top_srcdir)/m4/install.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
SOURCES =
DIST_SOURCES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(includedir)"
includeHEADERS_INSTALL = $(INSTALL_HEADER)
HEADERS = $(include_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
POW_LIB = @POW_LIB@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
XML2_CONFIG = @XML2_CONFIG@
XML_CPPFLAGS = @XML_CPPFLAGS@
XML_LIBS = @XML_LIBS@
YACC = @YACC@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
etcdir = @etcdir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
idb_brm_libs = @idb_brm_libs@
idb_cflags = @idb_cflags@
idb_common_includes = @idb_common_includes@
idb_common_ldflags = @idb_common_ldflags@
idb_common_libs = @idb_common_libs@
idb_cppflags = @idb_cppflags@
idb_cxxflags = @idb_cxxflags@
idb_exec_libs = @idb_exec_libs@
idb_ldflags = @idb_ldflags@
idb_oam_libs = @idb_oam_libs@
idb_write_libs = @idb_write_libs@
idbinstall = @idbinstall@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localdir = @localdir@
localstatedir = @localstatedir@
mandir = @mandir@
march_flags = @march_flags@
mibdir = @mibdir@
mkdir_p = @mkdir_p@
mysqldir = @mysqldir@
netsnmp_libs = @netsnmp_libs@
netsnmpagntdir = @netsnmpagntdir@
netsnmpdir = @netsnmpdir@
netsnmplibrdir = @netsnmplibrdir@
netsnmpmachdir = @netsnmpmachdir@
netsnmpsysdir = @netsnmpsysdir@
oldincludedir = @oldincludedir@
postdir = @postdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedir = @sharedir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
toolsdir = @toolsdir@
include_HEADERS = we_index.h we_define.h we_type.h we_fileop.h we_blockop.h we_dbfileop.h we_obj.h we_log.h we_simplesyslog.h we_convertor.h we_brm.h we_macro.h we_config.h we_cache.h we_stats.h we_bulkrollbackmgr.h we_typeext.h we_chunkmanager.h we_bulkrollbackfilecompressed.h we_bulkrollbackfilecompressedhdfs.h we_bulkrollbackfile.h we_rbmetawriter.h we_dbrootextenttracker.h we_confirmhdfsdbfile.h
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu writeengine/shared/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu writeengine/shared/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(includedir)" || $(mkdir_p) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
$(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; for p in $$list; do \
f=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
rm -f "$(DESTDIR)$(includedir)/$$f"; \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-libtool \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am: install-includeHEADERS
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-includeHEADERS uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool ctags distclean distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am \
install-includeHEADERS install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
ps ps-am tags uninstall uninstall-am uninstall-includeHEADERS \
uninstall-info-am
test:
coverage:
leakcheck:
docs:
bootstrap: install-data-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,96 @@
//------------------------------------------------------------------------------
// test driver used to test reloadable cache enhancement to we_config
// for bug 4486
// $Id$
//------------------------------------------------------------------------------
#include <iostream>
#include <vector>
#include <dbrm.h>
#include "we_config.h"
using namespace WriteEngine;
void test()
{
std::cout << "getDBRootByIdx(1): " <<
Config::getDBRootByIdx(1) << std::endl;
std::cout << "getDBRootByIdx(3): " <<
Config::getDBRootByIdx(3) << std::endl;
std::cout << "getDBRootByNum(1): " <<
Config::getDBRootByNum(1) << std::endl;
std::cout << "getDBRootByNum(3): " <<
Config::getDBRootByNum(3) << std::endl;
std::vector<unsigned short> dbRootIds;
Config::getRootIdList( dbRootIds );
std::cout << "getRootIdList: ";
for (unsigned k=0; k<dbRootIds.size(); k++) {
std::cout << dbRootIds[k] << ' '; }
std::cout << std::endl;
std::vector<std::string> dbRootPathList;
Config::getDBRootPathList( dbRootPathList );
std::cout << "getDBRootPathList: " << std::endl;
for (unsigned k=0; k<dbRootPathList.size(); k++)
std::cout << " " << k << ". " << dbRootPathList[k] << std::endl;
std::cout << "getBulkRoot(): " <<
Config::getBulkRoot() << std::endl;
std::cout << "DBRootCount(): " <<
Config::DBRootCount() << std::endl;
std::cout << "totalDBRootCount(): " <<
Config::totalDBRootCount() << std::endl;
std::cout << "getWaitPeriod(): " <<
Config::getWaitPeriod() << std::endl;
std::cout << "getFilePerColumnPartition(): " <<
Config::getFilesPerColumnPartition() << std::endl;
std::cout << "getExtentsPerSegmentFile(): " <<
Config::getExtentsPerSegmentFile() << std::endl;
std::cout << "getBulkProcessPriority(): " <<
Config::getBulkProcessPriority() << std::endl;
std::cout << "getBulkRollbackDir(): " <<
Config::getBulkRollbackDir() << std::endl;
std::cout << "getMaxFileSystemDiskUsage(): " <<
Config::getMaxFileSystemDiskUsage() << std::endl;
std::cout << "getNumCompressedPadBlks(): " <<
Config::getNumCompressedPadBlks() << std::endl;
std::cout << "getParentOAMModuleFlag(): " <<
Config::getParentOAMModuleFlag() << std::endl;
std::cout << "getLocalModuleType(): " <<
Config::getLocalModuleType() << std::endl;
std::cout << "getLocalModuleID(): " <<
Config::getLocalModuleID() << std::endl;
std::cout << "getVBRoot(): " <<
Config::getVBRoot() << std::endl;
}
int main()
{
Config::initConfigCache();
char resp;
int nTest = 0;
std::cout << std::endl;
while (1)
{
std::cout << "test" << nTest << "..." << std::endl;
test();
std::cout << "Pause..." << std::endl;
std::cin >> resp;
std::cout << std::endl;
if (resp == 'c')
{
std::cout << "Has local DBRootList changed: " <<
(bool)Config::hasLocalDBRootListChanged() << std::endl;
}
else if (resp == 'q')
{
break;
}
nTest++;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,282 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_blockop.cpp 4500 2013-01-31 20:25:42Z dhall $
*
*******************************************************************************/
/** @file */
#include <stdio.h>
#include <string.h>
#include "joblisttypes.h"
#include "we_blockop.h"
#include "we_config.h"
#include "we_brm.h"
#include "we_convertor.h"
using namespace execplan;
namespace WriteEngine
{
/**
* Constructor
*/
BlockOp::BlockOp()
{}
/**
* Default Destructor
*/
BlockOp::~BlockOp()
{}
/***********************************************************
* DESCRIPTION:
* Calculate the location of Row ID
* PARAMETERS:
* rowId - row id
* epb - entry per block
* width - width per column record
* RETURN:
* fbo - File block offset
* bio - Block internal offset
* true if success, false otherwise
***********************************************************/
bool BlockOp::calculateRowId(
RID rowId, const int epb, const int width, int& fbo, int& bio ) const
{
if( std::numeric_limits<WriteEngine::RID>::max() == rowId )
return false;
fbo = (int)( rowId/epb );
bio = ( rowId & ( epb - 1 )) * width;
return true;
}
/***********************************************************
* DESCRIPTION:
* Get the value that represents empty row
* PARAMETERS:
* colDataType - data type
* width - data width in byte
* RETURN:
* emptyVal - the value of empty row
***********************************************************/
uint64_t BlockOp::getEmptyRowValue(
const CalpontSystemCatalog::ColDataType colDataType, const int width ) const
{
uint64_t emptyVal = 0;
int offset = 0;
switch( colDataType ) {
case CalpontSystemCatalog::TINYINT : emptyVal = joblist::TINYINTEMPTYROW; break;
case CalpontSystemCatalog::SMALLINT: emptyVal = joblist::SMALLINTEMPTYROW; break;
case CalpontSystemCatalog::MEDINT :
case CalpontSystemCatalog::INT : emptyVal = joblist::INTEMPTYROW; break;
case CalpontSystemCatalog::BIGINT : emptyVal = joblist::BIGINTEMPTYROW; break;
case CalpontSystemCatalog::FLOAT :
case CalpontSystemCatalog::UFLOAT : emptyVal = joblist::FLOATEMPTYROW; break;
case CalpontSystemCatalog::DOUBLE :
case CalpontSystemCatalog::UDOUBLE : emptyVal = joblist::DOUBLEEMPTYROW; break;
case CalpontSystemCatalog::DECIMAL :
case CalpontSystemCatalog::UDECIMAL :
/* if( width <= 4 )
emptyVal = joblist::SMALLINTEMPTYROW;
else
if( width <= 9 )
emptyVal = 0x80000001;
else
if( width <= 18 )
emptyVal = 0x8000000000000001LL;
else
emptyVal = 0xFFFFFFFFFFFFFFFFLL;
*/
// @bug 194 use the correct logic in handling empty value for decimal
if (width <= 1)
emptyVal = joblist::TINYINTEMPTYROW;
else if( width <= 2 )
emptyVal = joblist::SMALLINTEMPTYROW;
else if( width <= 4 )
emptyVal = joblist::INTEMPTYROW;
else
emptyVal = joblist::BIGINTEMPTYROW;
break;
case CalpontSystemCatalog::UTINYINT : emptyVal = joblist::UTINYINTEMPTYROW; break;
case CalpontSystemCatalog::USMALLINT: emptyVal = joblist::USMALLINTEMPTYROW; break;
case CalpontSystemCatalog::UMEDINT :
case CalpontSystemCatalog::UINT : emptyVal = joblist::UINTEMPTYROW; break;
case CalpontSystemCatalog::UBIGINT : emptyVal = joblist::UBIGINTEMPTYROW; break;
case CalpontSystemCatalog::CHAR :
case CalpontSystemCatalog::VARCHAR :
case CalpontSystemCatalog::DATE :
case CalpontSystemCatalog::DATETIME :
default:
offset = ( colDataType == CalpontSystemCatalog::VARCHAR )? -1 : 0;
emptyVal = joblist::CHAR1EMPTYROW;
if( width == (2 + offset) )
emptyVal = joblist::CHAR2EMPTYROW;
else
if( width >= (3 + offset) && width <= ( 4 + offset ) )
emptyVal = joblist::CHAR4EMPTYROW;
else
if( width >= (5 + offset) )
emptyVal = joblist::CHAR8EMPTYROW;
break;
}
return emptyVal;
}
/***********************************************************
* DESCRIPTION:
* Get the correct width for a row
* PARAMETERS:
* colDataType - data type
* width - data width in byte
* RETURN:
* emptyVal - the value of empty row
***********************************************************/
int BlockOp::getCorrectRowWidth(
const CalpontSystemCatalog::ColDataType colDataType, const int width ) const
{
return Convertor::getCorrectRowWidth(colDataType, width);
}
/***********************************************************
* DESCRIPTION:
* Get row id
* PARAMETERS:
* fbo - file block offset
* bio - block internal offset
* bbo - byte internal offset
* RETURN:
* row id
***********************************************************/
RID BlockOp::getRowId(
const long fbo, const int width, const int rowPos
/*const int bio, const int bbo*/ ) const
{
// return fbo*BYTE_PER_BLOCK*ROW_PER_BYTE + bio*ROW_PER_BYTE + bbo;
return (BYTE_PER_BLOCK/width) * fbo + rowPos;
}
/***********************************************************
* DESCRIPTION:
* Get buffer value
* PARAMETERS:
* buf - buffer
* width - data width in byte
* RETURN:
* val - buffer value
***********************************************************/
void BlockOp::readBufValue(
const unsigned char* buf, void* val, const short width ) const
{
memcpy( val, buf, width );
}
/***********************************************************
* DESCRIPTION:
* Reset a buffer
* PARAMETERS:
* buf - buffer
* bufSize - buffer size
* RETURN:
* none
***********************************************************/
void BlockOp::resetBuf( unsigned char* buf, const int bufSize ) const
{
memset( buf, 0, bufSize );
}
/***********************************************************
* DESCRIPTION:
* Fill buffer with empty values
* PARAMETERS:
* buf - buffer
* bufSize - buffer size
* emptyVal - empty value
* width - type width
* RETURN:
* none
***********************************************************/
/* static */
void BlockOp::setEmptyBuf(
unsigned char* buf, const int bufSize, uint64_t emptyVal, const int width )
{
const int ARRAY_COUNT = 128;
const int NBYTES_IN_ARRAY = width * ARRAY_COUNT;
//unsigned char emptyValArray[NBYTES_IN_ARRAY];
unsigned char* emptyValArray = (unsigned char*)alloca(NBYTES_IN_ARRAY);
// Optimize buffer initialization by constructing and copying in an array
// instead of individual values. This reduces the number of calls to
// memcpy().
for (int j=0; j<ARRAY_COUNT; j++)
{
memcpy(emptyValArray+(j*width), &emptyVal, width);
}
int countFull128 = (bufSize/width) / ARRAY_COUNT;
int countRemain = (bufSize/width) % ARRAY_COUNT;
// Copy in the 128 element array into "buf" as many times as needed
if (countFull128 > 0)
{
for( int i = 0; i < countFull128; i++ )
memcpy( buf + (i * (NBYTES_IN_ARRAY)),
emptyValArray,
NBYTES_IN_ARRAY );
}
// Initialize the remainder of "buf" that is leftover
if (countRemain > 0)
{
memcpy( buf + (countFull128 * NBYTES_IN_ARRAY),
emptyValArray,
width*countRemain );
}
}
/***********************************************************
* DESCRIPTION:
* Set a value in a buffer
* PARAMETERS:
* buf - buffer
* val - buffer value
* width - data width in byte
* RETURN:
* none
***********************************************************/
void BlockOp::writeBufValue(
unsigned char* buf, void* val, const size_t width, const bool clear ) const
{
if( clear )
memset( buf, 0, width );
memcpy( buf, val, width );
}
} //end of namespace

View File

@ -0,0 +1,130 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_blockop.h 4450 2013-01-21 14:13:24Z rdempsey $
*
*******************************************************************************/
/** @file */
#ifndef _WE_BLOCKOP_H_
#define _WE_BLOCKOP_H_
#include <we_obj.h>
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
/** Class BlockOp */
class BlockOp : public WEObj
{
public:
/**
* @brief Constructor
*/
EXPORT BlockOp();
/**
* @brief Default Destructor
*/
EXPORT ~BlockOp();
/**
* @brief Calculate the location of Row ID
*/
EXPORT bool calculateRowId( RID rowId,
const int epb,
const int width,
int& fbo,
int& bio ) const;
/**
* @brief Calculate the location of Row ID
*/
void clearBlock( DataBlock* block )
{ memset(block->data, 0, sizeof(block->data));
block->no = -1;
block->dirty = false; }
/**
* @brief Get bit value after shift
*/
uint64_t getBitValue( uint64_t val,
int shiftBit,
uint64_t mask ) const
{ return ( val >> shiftBit ) & mask ; }
/**
* @brief Get correct row width
*/
EXPORT int getCorrectRowWidth( const execplan::CalpontSystemCatalog::ColDataType colDataType,
const int width ) const;
/**
* @brief Get an empty row value
*/
EXPORT uint64_t getEmptyRowValue(const execplan::CalpontSystemCatalog::ColDataType colDataType,
const int width ) const;
/**
* @brief Calculate row id
*/
EXPORT RID getRowId( const long fbo,
const int width,
const int rowPos ) const;
/**
* @brief Get buffer value
*/
EXPORT void readBufValue( const unsigned char* buf,
void* val, const short width ) const;
/**
* @brief Reset a buffer
*/
EXPORT void resetBuf( unsigned char* buf,
const int bufSize ) const;
/**
* @brief Fill buffer with empty values
*/
EXPORT void static setEmptyBuf( unsigned char* buf,
const int bufSize,
uint64_t emptyVal, const int width );
/**
* @brief Set a value in a buffer
*/
EXPORT void writeBufValue( unsigned char* buf,
void* val,
const size_t width,
const bool clear = false ) const;
};
} //end of namespace
#undef EXPORT
#endif // _WE_BLOCKOP_H_

File diff suppressed because it is too large Load Diff

710
writeengine/shared/we_brm.h Normal file
View File

@ -0,0 +1,710 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_brm.h 4726 2013-08-07 03:38:36Z bwilkinson $
*
*******************************************************************************/
/** @file */
#ifndef _WE_BRM_H_
#define _WE_BRM_H_
#include <iostream>
#include <vector>
#include <boost/thread.hpp>
#include <boost/thread/tss.hpp>
#include "brm.h"
#include "we_obj.h"
#include<sys/time.h>
#include "brmtypes.h"
#include "IDBDataFile.h"
#include "IDBPolicy.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
// forward reference
class DbFileOp;
/** Class BRMWrapper */
class BRMWrapper : public WEObj
{
public:
/**
* @brief Initialize an Auto Increment sequence for the specified OID
* @param colOID Column OID of interest
* @param startNextValue Starting next value for the AI sequence
* @param colWidth Width of the relevant column (in bytes)
* @param errMsg Applicable error message.
*/
EXPORT int startAutoIncrementSequence( OID colOID,
uint64_t startNextValue,
uint32_t colWidth,
execplan::CalpontSystemCatalog::ColDataType colDataType,
std::string& errMsg);
/**
* @brief Reserve a range of Auto Increment numbers for the specified OID
* @param colOID Column OID of interest
* @param count Requested range of auto increment numbers
* @param firstNum (out) First number of range that is reserved
* @param errMsg Applicable error message.
*/
EXPORT int getAutoIncrementRange( OID colOID,
uint64_t count,
uint64_t& firstNum,
std::string& errMsg);
/**
* @brief Inform BRM to add an extent to each of the requested OIDs at
* the specified DBRoot (and partition number if the DBRoot is empty).
* @param cols (in) List of column OIDs and column widths
* @param dbRoot (in) DBRoot for requested extents
* @param partition (in/out) Physical partition number in file path.
* If allocating OID's first extent for this DBRoot, then
* partition is input, else it is only for output.
* @param segmentNum (out) Segment number for new extents
* @param extents (out) List of lbids, numBlks, and fbo for new extents
*/
EXPORT int allocateStripeColExtents(
const std::vector<BRM::CreateStripeColumnExtentsArgIn>& cols,
uint16_t dbRoot,
uint32_t& partition,
uint16_t& segmentNum,
std::vector<BRM::CreateStripeColumnExtentsArgOut>& extents);
/**
* @brief Inform BRM to add extent to the exact segment file specified by
* OID, DBRoot, partition, and segment.
*/
EXPORT int allocateColExtentExactFile( const OID oid,
const uint32_t colWidth,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
execplan::CalpontSystemCatalog::ColDataType colDataType,
BRM::LBID_t& startLbid,
int& allocSize,
uint32_t& startBlock);
/**
* @brief Inform BRM to add a dictionary store extent to the specified OID
*/
EXPORT int allocateDictStoreExtent( const OID oid,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
BRM::LBID_t& startLbid,
int& allocSize );
/**
* @brief Inform BRM to delete certain oid
*/
EXPORT int deleteOid( const OID oid );
/**
* @brief Inform BRM to delete list of oids
*/
EXPORT int deleteOIDsFromExtentMap (const std::vector<int32_t>& oids);
/**
* @brief Get BRM information based on a specfic OID, DBRoot, partition,
* and segment
*/
EXPORT int getBrmInfo( const OID oid,
const uint32_t partition,
const uint16_t segment,
const int fbo,
BRM::LBID_t& lbid );
/**
* @brief Get starting LBID from BRM for a specfic OID, DBRoot, partition,
* segment, and block offset.
*/
EXPORT int getStartLbid( const OID oid,
const uint32_t partition,
const uint16_t segment,
const int fbo,
BRM::LBID_t& startLbid );
/**
* @brief Get the real physical offset based on the LBID
*/
EXPORT int getFboOffset( const uint64_t lbid,
uint16_t& dbRoot,
uint32_t& partition,
uint16_t& segment,
int& fbo );
EXPORT int getFboOffset( const uint64_t lbid, int& oid,
uint16_t& dbRoot,
uint32_t& partition,
uint16_t& segment,
int& fbo );
/**
* @brief Get last "local" HWM, partition, and segment for an OID and DBRoot
*/
EXPORT int getLastHWM_DBroot( OID oid,
uint16_t dbRoot,
uint32_t& partition,
uint16_t& segment,
HWM& hwm,
int& status,
bool& bFound);
/**
* @brief Get HWM for a specific OID, partition, and segment
*/
int getLocalHWM( OID oid ,
uint32_t partition,
uint16_t segment,
HWM& hwm,
int& status);
/**
* @brief Get HWM info for a specific OID and PM
*/
EXPORT int getDbRootHWMInfo( const OID oid ,
BRM::EmDbRootHWMInfo_v& emDbRootHwmInfos);
/**
* @brief Get status or state of the extents in the specified segment file.
* bFound flag indicates whether an extent was found or not.
*/
int getExtentState( OID oid,
uint32_t partition,
uint16_t segment,
bool& bFound,
int& status);
/**
* @brief Get extentRows
*/
unsigned getExtentRows();
/**
* @brief Return the extents info for specified OID
*/
int getExtents( int oid,
std::vector<struct BRM::EMEntry>& entries,
bool sorted, bool notFoundErr,
bool incOutOfService );
/**
* @brief Return the extents info for specified OID and dbroot
*/
int getExtents_dbroot( int oid,
std::vector<struct BRM::EMEntry>& entries,
const uint16_t dbroot);
/**
* @brief Return the read/write status of DBRM (helps detect if DBRM is up)
*/
EXPORT int isReadWrite();
/**
* @brief Return the state of the system state shutdown pending
* flags
*/
EXPORT int isShutdownPending(bool& bRollback, bool& bForce);
/**
* @brief Return the state of the system state suspend pending
* flags
*/
EXPORT int isSuspendPending();
/**
* @brief Is InfiniDB system ready (completed startup)
*/
bool isSystemReady();
/**
* @brief Lookup LBID ranges for column specified OID
*/
int lookupLbidRanges(OID oid, BRM::LBIDRange_v& lbidRanges);
/**
* @brief Mark extent invalid for causal partioning
*/
int markExtentInvalid(const uint64_t lbid,
const execplan::CalpontSystemCatalog::ColDataType colDataType);
/**
* @brief Mark multiple extents invalid for causal partioning
*/
int markExtentsInvalid(std::vector<BRM::LBID_t>& lbids,
const std::vector<execplan::CalpontSystemCatalog::ColDataType>&
colDataTypes);
/**
* @brief set extents CP min/max info into extent map
*/
int setExtentsMaxMin(const BRM::CPInfoList_t& cpinfoList);
/**
* @brief Perform bulk rollback of any column extents that logically follow
* the specified HWM for the given column OID and DBRoot. The HWM for the
* last local extent is reset to the specified hwm as well. Any extents in
* subsequent partitions are deleted. If bDeleteAll is true, then all
* extents for the specified oid and dbroot are deleted.
*/
int rollbackColumnExtents_DBroot( const OID oid,
bool bDeleteAll,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
BRM::HWM_t hwm );
/**
* @brief Perform bulk rollback of the extents that follow the specified
* dictionary extents for the given column OID and DBRoot. The HWM for
* the last retained extents, are reset as well. Any trailing segment
* files for the same parition, that are not specified in the hwm list,
* are deleted. Any extents in subsequent partitions are deleted. If
* segNums and hwms vector are empty, then all extents for the specified
* oid and dbroot are deleted.
*/
int rollbackDictStoreExtents_DBroot( OID oid,
uint16_t dbRoot,
uint32_t partition,
const std::vector<uint16_t>& segNums,
const std::vector<BRM::HWM_t>& hwms );
/**
* @brief Perform delete column extents
*/
int deleteEmptyColExtents(const std::vector<BRM::ExtentInfo>& extentsInfo);
/**
* @brief Perform delete dictionary extents
*/
int deleteEmptyDictStoreExtents(
const std::vector<BRM::ExtentInfo>& extentsInfo );
/**
* @brief Set HWM for a specific OID, partition, and segment
*/
int setLocalHWM( OID oid,
uint32_t partition,
uint16_t segment,
const HWM hwm );
//Set hwm for all columns in a table
int bulkSetHWM( const std::vector<BRM::BulkSetHWMArg> & vec,
BRM::VER_t transID);
/**
* @brief Atomically apply a batch of HWM and CP updates within the scope
* of a single BRM lock. CP info is merged with current min/max range.
* @param hwmArgs Vector of HWM updates
* @param mergeCPDataArgs Vector of Casual Partition updates
*/
int bulkSetHWMAndCP( const std::vector<BRM::BulkSetHWMArg>& hwmArgs,
const std::vector<BRM::CPInfoMerge>& mergeCPDataArgs);
/**
* @brief Acquire a table lock for the specified table OID.
* If nonzero lockID is returned, then the table is already locked.
* @param tableOID Table to be locked.
* @param ownerName Requested (in) and current (out) owner for the lock.
* @param processID Requested (in) and current (out) pid for the lock.
* @param sessionID Requested (in) and current (out) session ID for the lock
* @param transID Requested (in) and current (out) transacton of the lock
* @param lockID Assigned or current lock for the specified table.
* @param errMsg Applicable error message.
*/
EXPORT int getTableLock ( OID tableOid,
std::string& ownerName,
uint32_t& processID,
int32_t& sessionID,
int32_t& transID,
uint64_t& lockID,
std::string& errMsg);
/**
* @brief Change the state of the specified table lock ID.
* @param lockID Lock for which the status is to be changed.
* @param lockState New state to be assigned to the specified lock.
* @param bChanged Indicates whether lock state was changed.
* @param errMsg Applicable error message.
*/
EXPORT int changeTableLockState ( uint64_t lockID,
BRM::LockState lockState,
bool& bChanged,
std::string& errMsg);
/**
* @brief Release the specified table lock ID.
* @param lockID Lock to be released.
* @param bReleased Indicates whether lock was released.
* @param errMsg Applicable error message.
*/
EXPORT int releaseTableLock( uint64_t lockID,
bool& bReleased,
std::string& errMsg);
/**
* @brief Get current table lock information for the specified lock ID.
* @param lockID Lock to be retrieved.
* @param lockInfo Current lock information for the specified lock.
* @param blockExists Indicates whether lock was found.
* @param errMsg Applicable error message.
*/
EXPORT int getTableLockInfo( uint64_t lockID,
BRM::TableLockInfo* lockInfo,
bool& bLockExists,
std::string& errMsg);
/**
* @brief Tell BRM to make a snapshot of it's current state to disk.
*/
int takeSnapshot();
/**
* @brief Save brm structures to file
*/
EXPORT int saveState();
//--------------------------------------------------------------------------
// Non-inline Versioning Functions Start Here
//--------------------------------------------------------------------------
/**
* @brief Commit the transaction
*/
EXPORT int commit( const BRM::VER_t transID );
/**
* @brief Copy blocks between write engine and version buffer
*/
EXPORT int copyVBBlock( IDBDataFile* pSourceFile,
IDBDataFile* pTargetFile,
const uint64_t sourceFbo,
const uint64_t targetFbo,
DbFileOp* fileOp,
const Column& column );
EXPORT int copyVBBlock( IDBDataFile* pSourceFile,
const OID sourceOid,
IDBDataFile* pTargetFile,
const OID targetOid,
const std::vector<uint32_t>& fboList,
const BRM::VBRange& freeList,
size_t& nBlocksProcessed,
DbFileOp* pFileOp,
const size_t fboCurrentOffset = 0 );
/**
* @brief Rollback the specified transaction
*/
EXPORT int rollBack( const BRM::VER_t transID, int sessionId );
/**
* @brief Rollback the specified transaction
*/
EXPORT int rollBackVersion( const BRM::VER_t transID, int sessionId );
/**
* @brief Rollback the specified transaction
*/
EXPORT int rollBackBlocks( const BRM::VER_t transID, int sessionId );
/**
* @brief Write specified LBID to version buffer
*/
EXPORT int writeVB( IDBDataFile* pFile,
const BRM::VER_t transID,
const OID oid,
const uint64_t lbid,
DbFileOp* pFileOp );
int writeVB( IDBDataFile* pFile,
const BRM::VER_t transID,
const OID weOid,
std::vector<uint32_t>& fboList,
std::vector<BRM::LBIDRange>& rangeList,
DbFileOp* pFileOp,
std::vector<BRM::VBRange>& freeList,
uint16_t dbRoot,
bool skipBeginVBCopy = false);
void writeVBEnd(const BRM::VER_t transID,
std::vector<BRM::LBIDRange>& rangeList);
BRM::DBRM* getDbrmObject();
void pruneLBIDList(BRM::VER_t transID,
std::vector<BRM::LBIDRange> *rangeList,
std::vector<uint32_t> *fboList) const;
//--------------------------------------------------------------------------
// Non-inline Versioning Functions End Here
//--------------------------------------------------------------------------
/**
* @brief static functions
*/
EXPORT static BRMWrapper* getInstance();
EXPORT static int getBrmRc(bool reset=true);
static bool getUseVb() { return m_useVb; }
static void setUseVb( const bool val ) { m_useVb = val; }
private:
//--------------------------------------------------------------------------
// Private methods
//--------------------------------------------------------------------------
BRMWrapper();
~BRMWrapper();
// disable copy constructor and assignment operator
BRMWrapper(const BRMWrapper&);
BRMWrapper& operator= ( const BRMWrapper& wrapper );
// Convert BRM return code to WE return code
int getRC( int brmRc, int errRc );
EXPORT void saveBrmRc( int brmRc );
IDBDataFile* openFile( const File& fileInfo,
const char* mode,
const bool bCache = false );
//--------------------------------------------------------------------------
// Private data members
//--------------------------------------------------------------------------
static BRMWrapper* volatile m_instance;
static boost::thread_specific_ptr<int> m_ThreadDataPtr;
static boost::mutex m_instanceCreateMutex;
#if defined(_MSC_VER) && !defined(WRITEENGINE_DLLEXPORT)
__declspec(dllimport)
#endif
EXPORT static bool m_useVb;
static OID m_curVBOid;
static IDBDataFile* m_curVBFile;
BRM::DBRM* blockRsltnMgrPtr;
};
//------------------------------------------------------------------------------
// Inline functions
//------------------------------------------------------------------------------
inline BRMWrapper::BRMWrapper()
{
blockRsltnMgrPtr = new BRM::DBRM();
}
inline BRMWrapper::~BRMWrapper()
{
if (blockRsltnMgrPtr)
delete blockRsltnMgrPtr;
blockRsltnMgrPtr = 0;
}
inline BRM::DBRM* BRMWrapper::getDbrmObject()
{
return blockRsltnMgrPtr;
}
inline int BRMWrapper::getRC( int brmRc, int errRc )
{
if (brmRc == BRM::ERR_OK)
return NO_ERROR;
saveBrmRc( brmRc );
return errRc;
}
inline int BRMWrapper::getLastHWM_DBroot( OID oid,
uint16_t dbRoot,
uint32_t& partition,
uint16_t& segment,
HWM& hwm,
int& status,
bool& bFound)
{
int rc = blockRsltnMgrPtr->getLastHWM_DBroot(
(BRM::OID_t)oid, dbRoot, partition, segment, hwm,
status, bFound);
return getRC( rc, ERR_BRM_GET_HWM );
}
inline int BRMWrapper::getLocalHWM( OID oid ,
uint32_t partition,
uint16_t segment,
HWM& hwm,
int& status)
{
int rc = blockRsltnMgrPtr->getLocalHWM(
(BRM::OID_t)oid, partition, segment, hwm, status);
return getRC( rc, ERR_BRM_GET_HWM );
}
inline int BRMWrapper::getExtentState( OID oid,
uint32_t partition,
uint16_t segment,
bool& bFound,
int& status)
{
int rc = blockRsltnMgrPtr->getExtentState(
(BRM::OID_t)oid, partition, segment, bFound, status);
return getRC( rc, ERR_BRM_GET_EXT_STATE );
}
inline unsigned BRMWrapper::getExtentRows()
{
return blockRsltnMgrPtr->getExtentRows( );
}
inline int BRMWrapper::getExtents( int oid,
std::vector<struct BRM::EMEntry>& entries,
bool sorted, bool notFoundErr,
bool incOutOfService )
{
int rc = blockRsltnMgrPtr->getExtents(
oid, entries, sorted, notFoundErr, incOutOfService);
return rc;
}
inline int BRMWrapper::getExtents_dbroot( int oid,
std::vector<struct BRM::EMEntry>& entries,
const uint16_t dbroot )
{
int rc = blockRsltnMgrPtr->getExtents_dbroot(
oid, entries, dbroot);
return rc;
}
inline bool BRMWrapper::isSystemReady()
{
return blockRsltnMgrPtr->getSystemReady() > 0 ? true : false;
}
inline int BRMWrapper::lookupLbidRanges( OID oid, BRM::LBIDRange_v& lbidRanges)
{
int rc = blockRsltnMgrPtr->lookup( oid, lbidRanges );
return getRC( rc, ERR_BRM_LOOKUP_LBID_RANGES );
}
inline int BRMWrapper::markExtentInvalid( const uint64_t lbid,
const execplan::CalpontSystemCatalog::ColDataType colDataType )
{
int rc = blockRsltnMgrPtr->markExtentInvalid( lbid, colDataType );
return getRC( rc, ERR_BRM_MARK_INVALID );
}
inline int BRMWrapper::markExtentsInvalid(std::vector<BRM::LBID_t>& lbids,
const std::vector<execplan::CalpontSystemCatalog::ColDataType>&
colDataTypes)
{
int rc = 0;
if (idbdatafile::IDBPolicy::useHdfs())
return rc;
rc = blockRsltnMgrPtr->markExtentsInvalid(lbids, colDataTypes);
return getRC( rc, ERR_BRM_MARK_INVALID );
}
inline int BRMWrapper::bulkSetHWMAndCP(
const std::vector<BRM::BulkSetHWMArg>& hwmArgs,
const std::vector<BRM::CPInfoMerge>& mergeCPDataArgs)
{
std::vector<BRM::CPInfo> setCPDataArgs; // not used
BRM::VER_t transID = 0; // n/a
int rc = blockRsltnMgrPtr->bulkSetHWMAndCP(
hwmArgs, setCPDataArgs, mergeCPDataArgs, transID );
return getRC( rc, ERR_BRM_BULK_UPDATE );
}
inline int BRMWrapper::setExtentsMaxMin(const BRM::CPInfoList_t& cpinfoList)
{
int rc = blockRsltnMgrPtr->setExtentsMaxMin( cpinfoList );
return getRC( rc, ERR_BRM_SET_EXTENTS_CP );
}
inline int BRMWrapper::rollbackColumnExtents_DBroot( const OID oid,
bool bDeleteAll,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
BRM::HWM_t hwm )
{
int rc = blockRsltnMgrPtr->rollbackColumnExtents_DBroot (
oid, bDeleteAll, dbRoot, partition, segment, hwm );
return getRC( rc, ERR_BRM_BULK_RB_COLUMN );
}
inline int BRMWrapper::rollbackDictStoreExtents_DBroot( OID oid,
uint16_t dbRoot,
uint32_t partition,
const std::vector<uint16_t>& segNums,
const std::vector<BRM::HWM_t>& hwms )
{
int rc = blockRsltnMgrPtr->rollbackDictStoreExtents_DBroot (
oid, dbRoot, partition, segNums, hwms );
return getRC( rc, ERR_BRM_BULK_RB_DCTNRY );
}
inline int BRMWrapper::deleteEmptyColExtents(
const std::vector<BRM::ExtentInfo>& extentsInfo )
{
int rc = blockRsltnMgrPtr->deleteEmptyColExtents ( extentsInfo );
return getRC( rc, ERR_BRM_DELETE_EXTENT_COLUMN );
}
inline int BRMWrapper::deleteEmptyDictStoreExtents(
const std::vector<BRM::ExtentInfo>& extentsInfo )
{
int rc = blockRsltnMgrPtr->deleteEmptyDictStoreExtents ( extentsInfo );
return getRC( rc, ERR_BRM_DELETE_EXTENT_DCTNRY );
}
inline int BRMWrapper::setLocalHWM( OID oid,
uint32_t partition,
uint16_t segment,
const HWM hwm )
{
int rc = blockRsltnMgrPtr->setLocalHWM(
(int)oid, partition, segment, hwm);
return getRC( rc, ERR_BRM_SET_HWM );
}
inline int BRMWrapper::bulkSetHWM( const std::vector<BRM::BulkSetHWMArg> & vec,
BRM::VER_t transID = 0)
{
int rc = blockRsltnMgrPtr->bulkSetHWM( vec, transID);
return getRC( rc, ERR_BRM_SET_HWM );
}
inline int BRMWrapper::takeSnapshot()
{
int rc = blockRsltnMgrPtr->takeSnapshot();
return getRC( rc, ERR_BRM_TAKE_SNAPSHOT );
}
} //end of namespace
#undef EXPORT
#endif // _WE_BRM_H_

View File

@ -0,0 +1,485 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
* $Id: we_bulkrollbackfile.cpp 4737 2013-08-14 20:45:46Z bwilkinson $
*/
#include "we_bulkrollbackfile.h"
#include "we_bulkrollbackmgr.h"
#include <sstream>
#include "we_define.h"
#include "we_fileop.h"
#include "messageids.h"
#include "IDBDataFile.h"
using namespace idbdatafile;
using namespace execplan;
namespace WriteEngine
{
//------------------------------------------------------------------------------
// BulkRollbackFile constructor
//------------------------------------------------------------------------------
BulkRollbackFile::BulkRollbackFile(BulkRollbackMgr* mgr) : fMgr(mgr)
{
// Initialize empty dictionary header block used when reinitializing
// dictionary store extents.
const uint16_t freeSpace = BYTE_PER_BLOCK -
(HDR_UNIT_SIZE + NEXT_PTR_BYTES + HDR_UNIT_SIZE + HDR_UNIT_SIZE);
const uint64_t nextPtr = NOT_USED_PTR;
const uint16_t offSetZero = BYTE_PER_BLOCK;
const uint16_t endHeader = DCTNRY_END_HEADER;
memcpy(fDctnryHdr, &freeSpace, HDR_UNIT_SIZE);
memcpy(fDctnryHdr+ HDR_UNIT_SIZE, &nextPtr, NEXT_PTR_BYTES);
memcpy(fDctnryHdr+ HDR_UNIT_SIZE + NEXT_PTR_BYTES,
&offSetZero, HDR_UNIT_SIZE);
memcpy(fDctnryHdr+ HDR_UNIT_SIZE + NEXT_PTR_BYTES + HDR_UNIT_SIZE,
&endHeader, HDR_UNIT_SIZE);
}
//------------------------------------------------------------------------------
// BulkRollbackFile destructor
//------------------------------------------------------------------------------
BulkRollbackFile::~BulkRollbackFile()
{
}
//------------------------------------------------------------------------------
// Build the specified database segment file name.
//
// columnOID - OID of segment file to be found
// fileTypeFlag - true -> column file; false -> dictionary store file
// dbRoot - DBRoot of segment file to be found
// partNum - Partition number of segment file to be found
// segNum - Segment number of segment file to be found
// segFileName (out) - Name of segment file
//------------------------------------------------------------------------------
void BulkRollbackFile::buildSegmentFileName(
OID columnOID,
bool fileTypeFlag,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
std::string& segFileName )
{
char fileName[FILE_NAME_SIZE];
int rc = fDbFile.getFileName( columnOID, fileName,
dbRoot, partNum, segNum );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error constructing " <<
(fileTypeFlag ? "column" : "dictionary store") <<
" filename for deletion" <<
"; columnOID-" << columnOID <<
"; dbRoot-" << dbRoot <<
"; partNum-" << partNum <<
"; segNum-" << segNum <<
"; " << ec.errorString(rc);
throw WeException( oss.str(), rc );
}
segFileName = fileName;
}
//------------------------------------------------------------------------------
// Delete the specified database segment file.
//
// columnOID - OID of segment file to be deleted
// fileTypeFlag - true -> column file; false -> dictionary store file
// dbRoot - DBRoot of segment file to be deleted
// partNum - Partition number of segment file to be deleted
// segNum - Segment number of segment file to be deleted
// segFileName - Name of file to be deleted
//------------------------------------------------------------------------------
void BulkRollbackFile::deleteSegmentFile(
OID columnOID,
bool fileTypeFlag,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
const std::string& segFileName )
{
std::ostringstream msgText;
msgText << "Deleting " << (fileTypeFlag ? "column" : "dictionary store") <<
" file: dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText.str() );
// delete the db segment file if it exists
int rc = fDbFile.deleteFile( segFileName.c_str() );
if (rc != NO_ERROR)
{
if (rc != ERR_FILE_NOT_EXIST)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error deleting segment file"
"; columnOID-" << columnOID <<
"; dbRoot-" << dbRoot <<
"; partNum-" << partNum <<
"; segNum-" << segNum <<
"; " << ec.errorString(rc);
throw WeException( oss.str(), rc );
}
}
}
//------------------------------------------------------------------------------
// Truncate the specified database segment file to the given file offset.
//
// columnOID - OID of segment file to be truncated
// dbRoot - DBRoot of segment file to be truncated
// partNum - Partition number of segment file to be truncated
// segNum - Segment number of segment file to be truncated
// fileSizeBlocks - Number of blocks to be left in the file. Remainder of file
// is to be truncated.
//------------------------------------------------------------------------------
void BulkRollbackFile::truncateSegmentFile(
OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long fileSizeBlocks )
{
long long fileSizeBytes = fileSizeBlocks * BYTE_PER_BLOCK;
std::ostringstream msgText;
msgText << "Truncating column file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; totBlks-" << fileSizeBlocks <<
"; fileSize(bytes)-" << fileSizeBytes;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText.str() );
std::string segFile;
IDBDataFile* pFile = fDbFile.openFile(columnOID, dbRoot, partNum, segNum, segFile);
if (pFile == 0)
{
std::ostringstream oss;
oss << "Error opening column segment file to rollback extents "
"from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), ERR_FILE_OPEN );
}
int rc = fDbFile.truncateFile( pFile, fileSizeBytes );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error truncating column extents from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
fDbFile.closeFile( pFile );
}
//------------------------------------------------------------------------------
// Reinitialize a column segment extent (in the db file) to empty values,
// following the HWM. Remaining extents in the file are truncated.
//
// columnOID - OID of segment file to be reinitialized
// dbRoot - DBRoot of segment file to be reinitialized
// partNum - Partition number of segment file to be reinitialized
// segNum - Segment number of segment file to be reinitialized
// startOffsetBlk - File offset (after the HWM block), at which the file is
// to be reinitialized. Value is in blocks.
// nBlocks - Number of blocks to be reinitialized
// colType - Data type of the applicable column
// colWidth - Width in bytes, of the applicable column
// restoreHwmChk - Specifies whether HWM chunk is to be restored. n/a for
// uncompressed, but defined in this base class for the
// compressed derived class.
//------------------------------------------------------------------------------
void BulkRollbackFile::reInitTruncColumnExtent(
OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks,
CalpontSystemCatalog::ColDataType colType,
uint32_t colWidth,
bool /*restoreHwmChk*/ )
{
long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
std::ostringstream msgText;
msgText << "Reinit HWM column extent in db file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; offset(bytes)-" << startOffset <<
"; freeBlks-" << nBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText.str() );
std::string segFile;
IDBDataFile* pFile = fDbFile.openFile(columnOID, dbRoot, partNum, segNum, segFile);
if (pFile == 0)
{
std::ostringstream oss;
oss << "Error opening HWM column segment file to rollback extents "
"from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), ERR_FILE_OPEN );
}
// nBlocks is based on full extents, but if the database file only has an
// abbreviated extent, then we reset nBlocks to reflect the size of the file
// (Only the 1st extent in part0, seg0 employs an abbreviated extent.)
// DMC-SHARED_NOTHING_NOTE: Is it safe to assume only part0 seg0 is abbreviated?
if ((partNum == 0) && (segNum == 0))
{
long long nBytesInAbbrevExtent = INITIAL_EXTENT_ROWS_TO_DISK * colWidth;
if (startOffset <= nBytesInAbbrevExtent)
{
// This check would prevent us from truncating back to an
// abbreviated extent if the failed import expanded the initial
// extent; but when adding compression, decided to go ahead and
// truncate back to an abbreviated extent.
//long long fileSizeBytes;
//int rc = fDbFile.getFileSize2(pFile,fileSizeBytes);
//if (fileSizeBytes == nBytesInAbbrevExtent)
{
nBlocks = (nBytesInAbbrevExtent-startOffset) / BYTE_PER_BLOCK;
std::ostringstream msgText2;
msgText2 << "Reinit (abbrev) HWM column extent in db file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; offset(bytes)-" << startOffset <<
"; freeBlks-" << nBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText2.str() );
}
}
}
// Initialize the remainder of the extent after the HWM block
uint64_t emptyVal = fDbFile.getEmptyRowValue( colType, colWidth );
int rc = fDbFile.reInitPartialColumnExtent( pFile,
startOffset,
nBlocks,
emptyVal,
colWidth );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error rolling back HWM column extent from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// Truncate the remainder of the file
rc = fDbFile.truncateFile( pFile, pFile->tell() );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error truncating post-HWM column extents "
"from HWM segment DB file for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
fDbFile.closeFile( pFile );
}
//------------------------------------------------------------------------------
// Reinitialize a dictionary segment extent (in the db file) to empty blocks,
// following the HWM. Remaining extents in the file are truncated.
//
// dStoreOID - OID of segment store file to be reinitialized
// dbRoot - DBRoot of segment file to be reinitialized
// partNum - Partition number of segment file to be reinitialized
// segNum - Segment number of segment file to be reinitialized
// startOffsetBlk - Starting block (after the HWM block), at which the file is
// to be reinitialized. Value is in raw data blocks.
// nBlocks - Number of blocks to be reinitialized
//------------------------------------------------------------------------------
void BulkRollbackFile::reInitTruncDctnryExtent(
OID dStoreOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks )
{
long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
std::ostringstream msgText;
msgText << "Reinit dictionary store extent in db file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; offset(bytes)-" << startOffset <<
"; numblks-" << nBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, dStoreOID, msgText.str() );
std::string segFile;
IDBDataFile* pFile = fDbFile.openFile(dStoreOID, dbRoot, partNum, segNum, segFile);
if (pFile == 0)
{
std::ostringstream oss;
oss << "Error opening dictionary store segment file to rollback extents"
" from DB for" <<
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), ERR_FILE_OPEN );
}
// nBlocks is based on full extents, but if the database file only has an
// abbreviated extent, then we reset nBlocks to reflect the size of the file
// (Unlike column files which only employ an abbreviated extent for the
// 1st extent in part0, seg0, all new store files start with abbrev extent)
const uint32_t PSEUDO_COL_WIDTH = 8; // simulated col width for dictionary
long long nBytesInAbbrevExtent = INITIAL_EXTENT_ROWS_TO_DISK *
PSEUDO_COL_WIDTH;
if (startOffset <= nBytesInAbbrevExtent)
{
// This check would prevent us from truncating back to an
// abbreviated extent if the failed import expanded the initial
// extent; but when adding compression, decided to go ahead and
// truncate back to an abbreviated extent.
//long long fileSizeBytes;
//int rc = fDbFile.getFileSize2(pFile,fileSizeBytes);
//if (fileSizeBytes == nBytesInAbbrevExtent)
{
nBlocks = (nBytesInAbbrevExtent-startOffset) / BYTE_PER_BLOCK;
std::ostringstream msgText2;
msgText2 << "Reinit (abbrev) dictionary store extent in db file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; offset(bytes)-" << startOffset <<
"; numblks-" << nBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, dStoreOID, msgText2.str() );
}
}
// Initialize the remainder of the extent after the HWM block
int rc = fDbFile.reInitPartialDctnryExtent( pFile,
startOffset,
nBlocks,
fDctnryHdr,
DCTNRY_HEADER_SIZE );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error rolling back HWM dictionary store extent from DB for" <<
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// Truncate the remainder of the file
rc = fDbFile.truncateFile( pFile, pFile->tell() );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error truncating post-HWM dictionary store extents "
"from DB file for" <<
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
fDbFile.closeFile( pFile );
}
//------------------------------------------------------------------------------
// For uncompressed data...
// Always return true, in order to always reInit the post-HWM blocks for the
// HWM extent to empty values.
// This function is defined as a stub, so that the derived compression
// class can override this functionality, and return true or false depending
// on whether the HWM chunk was modified and backed up to disk.
//------------------------------------------------------------------------------
bool BulkRollbackFile::doWeReInitExtent( OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum) const
{
return true;
}
} //end of namespace

View File

@ -0,0 +1,207 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
* $Id: we_bulkrollbackfile.h 4675 2013-06-13 15:20:37Z dcathey $
*/
/** @file
* Contains class to restore db files on behalf of BulkRollBackMgr.
* In some cases this means restoring an extent to it's previous state.
* In some cases, it may mean removing extent(s) that were added to a file.
* In other cases it may mean completely deleting a db segment file, if that
* file did not exist prior to an aborted bulk load.
*/
#ifndef WE_BULKROLLBACKFILE_H_
#define WE_BULKROLLBACKFILE_H_
#include <string>
#include "we_define.h"
#include "we_type.h"
#include "we_fileop.h"
namespace WriteEngine
{
class BulkRollbackMgr;
//------------------------------------------------------------------------------
/** @brief Class used by BulkRollbackMgr to restore db files.
*/
//------------------------------------------------------------------------------
class BulkRollbackFile
{
public:
/** @brief BulkRollbackFile constructor
* @param mgr The controlling BulkRollbackMgr object.
*/
BulkRollbackFile(BulkRollbackMgr* mgr);
/** @brief BulkRollbackFile destructor
*/
virtual ~BulkRollbackFile();
/** @brief Construct the relevant db filename.
* Warning: This function may throw a WeException.
*
* @param columnOID OID of the segment file to be deleted
* @param fileTypeFlag file type (true->column; false->dictionary)
* @param dbRoot DBRoot of the segment file to be deleted
* @param partNum Partition number of the segment file to be deleted
* @param segNum Segment number of the segment file to be deleted
* @param segFileName (out) Name of segment file
*/
void buildSegmentFileName(OID columnOID,
bool fileTypeFlag,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
std::string& segFileName);
/** @brief Delete a segment file.
* Warning: This function may throw a WeException.
*
* @param columnOID OID of the segment file to be deleted
* @param fileTypeFlag file type (true->column; false->dictionary)
* @param dbRoot DBRoot of the segment file to be deleted
* @param partNum Partition number of the segment file to be deleted
* @param segNum Segment number of the segment file to be deleted
* @param segFileName Name of segment file to be deleted
*/
void deleteSegmentFile(OID columnOID,
bool fileTypeFlag,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
const std::string& segFileName );
/** @brief Construct a directory path.
*
* @param oid (in) OID to use in constructing directory path
* @param dbRoot (in) DBRoot to use in constructing directory path
* @param partition (in) Partition number to use in constructing dir path
* @param dirName (out)Directory path constructed from input arguments
* @return returns NO_ERROR if success
*/
int buildDirName( OID oid,
uint16_t dbRoot,
uint32_t partition,
std::string& dirName);
/** @brief Do we reinit trailing blocks in the HWM extent for the specified
* segment file
*
* The base behavior of this function always returns true, to reinit
* any trailing blocks in the HWM extent (for uncompressed data) to
* empty values.
*
* @param columnOID OID of the segment file in question
* @param dbRoot DBRoot for the segment file in question
* @param partNum Partition number for the segment file in question
* @param segNum Segment number for the segment file in question
*/
virtual bool doWeReInitExtent( OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum) const;
/** @brief Reinitialize the specified column segment file starting at
* startOffsetBlk, and truncate trailing extents.
* Warning: This function may throw a WeException.
*
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param startOffsetBlk Starting block offset where file is to be
* reinitialized
* @param nBlocks Number of blocks to be reinitialized
* @param colType Column type of the relevant segment file
* @param colWidth Width in bytes of column.
* @param restoreHwmChk Restore HWM chunk (n/a to uncompressed)
*/
virtual void reInitTruncColumnExtent(OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks,
execplan::CalpontSystemCatalog::ColDataType colType,
uint32_t colWidth,
bool restoreHwmChk );
/** @brief Reinitialize the specified dictionary store segment file starting
* at startOffsetBlk, and truncate trailing extents.
* Warning: This function may throw a WeException.
*
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param startOffsetBlk Starting block offset where file is to be
* reinitialized
* @param nBlocks Number of blocks to be reinitialized
*/
virtual void reInitTruncDctnryExtent(OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks );
/** @brief Truncate the specified segment file to a specified num of bytes
* Warning: This function may throw a WeException.
*
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param fileSizeBlocks Number of blocks to retain in the file
*/
virtual void truncateSegmentFile( OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long filesSizeBlocks );
protected:
BulkRollbackMgr* fMgr; // Bulk Rollback controller
FileOp fDbFile; // interface to DB file
unsigned char fDctnryHdr[DCTNRY_HEADER_SIZE]; // empty dctnry store blk
private:
// Disable unnecessary copy constructor and assignment operator
BulkRollbackFile(const BulkRollbackFile& rhs);
BulkRollbackFile& operator=(const BulkRollbackFile& rhs);
};
//------------------------------------------------------------------------------
// Inline functions
//------------------------------------------------------------------------------
inline int BulkRollbackFile::buildDirName( OID oid,
uint16_t dbRoot,
uint32_t partition,
std::string& dirName)
{
return fDbFile.getDirName( oid, dbRoot, partition, dirName );
}
} //end of namespace
#endif // WE_BULKROLLBACKFILE_H_

View File

@ -0,0 +1,988 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
* $Id: we_bulkrollbackfilecompressed.cpp 4737 2013-08-14 20:45:46Z bwilkinson $
*/
#include "we_bulkrollbackfilecompressed.h"
#include <sstream>
#include <boost/scoped_array.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/convenience.hpp>
#include "we_define.h"
#include "we_fileop.h"
#include "we_bulkrollbackmgr.h"
#include "we_convertor.h"
#include "messageids.h"
#include "IDBDataFile.h"
#include "IDBPolicy.h"
using namespace idbdatafile;
using namespace compress;
using namespace execplan;
namespace
{
const char* DATA_DIR_SUFFIX = "_data";
}
namespace WriteEngine
{
//------------------------------------------------------------------------------
// BulkRollbackFileCompressed constructor
//------------------------------------------------------------------------------
BulkRollbackFileCompressed::BulkRollbackFileCompressed(BulkRollbackMgr* mgr) :
BulkRollbackFile(mgr)
{
}
//------------------------------------------------------------------------------
// BulkRollbackFileCompressed destructor
//------------------------------------------------------------------------------
BulkRollbackFileCompressed::~BulkRollbackFileCompressed()
{
}
//------------------------------------------------------------------------------
// Truncate the specified database segment file to the extent specified by
// the given file offset. Also updates the header(s) as well.
//
// columnOID - OID of segment file to be truncated
// dbRoot - DBRoot of segment file to be truncated
// partNum - Partition number of segment file to be truncated
// segNum - Segment number of segment file to be truncated
// fileSizeBlocks - Number of raw data blocks to be left in the file.
// Remainder of file is to be truncated.
//------------------------------------------------------------------------------
void BulkRollbackFileCompressed::truncateSegmentFile(
OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long fileSizeBlocks )
{
std::ostringstream msgText1;
msgText1 << "Truncating compressed column file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; rawTotBlks-" << fileSizeBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText1.str() );
std::string segFile;
IDBDataFile* pFile = fDbFile.openFile(columnOID, dbRoot, partNum, segNum, segFile);
if (pFile == 0)
{
std::ostringstream oss;
oss << "Error opening compressed column segment file to rollback "
"extents from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), ERR_FILE_OPEN );
}
// Read and parse the header pointers
char hdrs[ IDBCompressInterface::HDR_BUF_LEN * 2 ];;
CompChunkPtrList chunkPtrs;
std::string errMsg;
int rc = loadColumnHdrPtrs(pFile, hdrs, chunkPtrs, errMsg);
if (rc != NO_ERROR)
{
std::ostringstream oss;
oss << "Error reading compressed column ptr headers from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << errMsg;
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// Locate the chunk containing the last block we intend to keep
unsigned int blockOffset = fileSizeBlocks - 1;
unsigned int chunkIndex = 0;
unsigned int blkOffsetInChunk = 0;
fCompressor.locateBlock( blockOffset, chunkIndex, blkOffsetInChunk );
// Truncate the extra extents that are to be aborted
if (chunkIndex < chunkPtrs.size())
{
long long fileSizeBytes = chunkPtrs[chunkIndex].first +
chunkPtrs[chunkIndex].second;
std::ostringstream msgText2;
msgText2 << "Compressed column file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; truncated to " << fileSizeBytes << " bytes";
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText2.str() );
// Drop off any trailing pointers (that point beyond the last block)
fCompressor.setBlockCount( hdrs, fileSizeBlocks );
std::vector<uint64_t> ptrs;
for (unsigned i=0; i<=chunkIndex; i++)
{
ptrs.push_back( chunkPtrs[i].first );
}
ptrs.push_back( chunkPtrs[chunkIndex].first +
chunkPtrs[chunkIndex].second );
fCompressor.storePtrs( ptrs, hdrs );
rc = fDbFile.writeHeaders( pFile, hdrs );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error writing compressed column headers to DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// Finally, we truncate the data base column segment file
rc = fDbFile.truncateFile( pFile, fileSizeBytes );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error truncating compressed column extents from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
} // end of (chunkIndex < chunkPtrs.size())
fDbFile.closeFile( pFile );
}
//------------------------------------------------------------------------------
// Reinitialize a column segment extent (in the db file) to empty values,
// following the HWM. Remaining extents in the file are truncated.
// Also updates the header(s) as well.
//
// columnOID - OID of segment file to be reinitialized
// dbRoot - DBRoot of segment file to be reinitialized
// partNum - Partition number of segment file to be reinitialized
// segNum - Segment number of segment file to be reinitialized
// startOffsetBlk - File offset (after the HWM block), at which the file is
// to be reinitialized. Value is in raw data blocks.
// nBlocks - Number of blocks to be reinitialized
// colType - Data type of the applicable column
// colWidth - Width in bytes, of the applicable column
// restoreHwmChk - Specifies whether HWM chunk is to be restored.
//------------------------------------------------------------------------------
void BulkRollbackFileCompressed::reInitTruncColumnExtent(
OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks,
CalpontSystemCatalog::ColDataType colType,
uint32_t colWidth,
bool restoreHwmChk )
{
long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
std::ostringstream msgText1;
msgText1 << "Reinit HWM compressed column extent in db file" <<
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; rawOffset(bytes)-"<< startOffset <<
"; rawFreeBlks-" << nBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText1.str() );
std::string segFile;
IDBDataFile* pFile = fDbFile.openFile(columnOID, dbRoot, partNum, segNum, segFile);
if (pFile == 0)
{
std::ostringstream oss;
oss << "Error opening compressed column segment file to rollback "
"extents from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), ERR_FILE_OPEN );
}
// Read and parse the header pointers
char hdrs[ IDBCompressInterface::HDR_BUF_LEN * 2 ];
CompChunkPtrList chunkPtrs;
std::string errMsg;
int rc = loadColumnHdrPtrs(pFile, hdrs, chunkPtrs, errMsg);
if (rc != NO_ERROR)
{
std::ostringstream oss;
oss << "Error reading compressed column ptr headers from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << errMsg;
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// Locate the chunk containing the last block we intend to keep
unsigned int blockOffset = startOffsetBlk - 1;
unsigned int chunkIndex = 0;
unsigned int blkOffsetInChunk = 0;
fCompressor.locateBlock( blockOffset, chunkIndex, blkOffsetInChunk );
if (chunkIndex < chunkPtrs.size())
{
// Read backup copy of HWM chunk and restore it's contents
uint64_t restoredChunkLen = 0;
uint64_t restoredFileSize = 0;
if (restoreHwmChk)
{
rc = restoreHWMChunk(pFile, columnOID, partNum, segNum,
chunkPtrs[chunkIndex].first,
restoredChunkLen, restoredFileSize, errMsg);
if (rc != NO_ERROR)
{
std::ostringstream oss;
oss << "Error restoring HWM chunk for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; blkoff-" << blockOffset <<
"; " << errMsg;
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
}
else
{
restoredChunkLen = chunkPtrs[chunkIndex].second;
// leave truncated to last chunk if no extra blocks needed
if (nBlocks == 0)
restoredFileSize = chunkPtrs[chunkIndex].first +
chunkPtrs[chunkIndex].second;
else
restoredFileSize = (chunkPtrs[chunkIndex].first +
chunkPtrs[chunkIndex].second) +
(uint64_t)(nBlocks * BYTE_PER_BLOCK);
}
// nBlocks is based on full extents, but if database file only has an
// abbreviated extent, then we reset nBlocks to reflect the size of a
// file with a single abbreviated extent.
// (Only the 1st extent in part0, seg0 employs an abbreviated extent.)
bool bAbbreviatedExtent = false;
// DMC-SHARED_NOTHING_NOTE: Is it safe to assume only part0 seg0 is abbreviated?
if ((partNum == 0) && (segNum == 0))
{
long long nBytesInAbbrevExtent = INITIAL_EXTENT_ROWS_TO_DISK *
colWidth;
if (startOffset <= nBytesInAbbrevExtent)
{
nBlocks = (nBytesInAbbrevExtent-startOffset) / BYTE_PER_BLOCK;
bAbbreviatedExtent = true;
}
}
long long fileSizeBytes = restoredFileSize;
std::ostringstream msgText2;
msgText2 << "HWM compressed column file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum;
if (bAbbreviatedExtent) // log adjusted nBlock count for abbrev extent
msgText2 << "; rawFreeBlks-" << nBlocks << " (abbrev)";
msgText2 << "; restoredChunk-" << restoredChunkLen << " bytes";
if (!restoreHwmChk)
msgText2 << " (no change)";
msgText2 << "; truncated to " << fileSizeBytes << " bytes";
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText2.str() );
// Initialize the remainder of the extent after the HWM chunk.
// Just doing an ftruncate() reinits the file to 0's, which may or may
// not actually reserve disk space if ftruncate is growing the file.
// So reinit the blocks by calling reInitPartialColumnExtent() to help
// avoid disk fragmentation. Be careful not to init > 1 extent, be-
// cause that is the limit on what that function was intended to do.
const unsigned BLKS_PER_EXTENT =
(BRMWrapper::getInstance()->getExtentRows() * colWidth) /
BYTE_PER_BLOCK;
long long nBlocksToInit = (fileSizeBytes -
(chunkPtrs[chunkIndex].first + restoredChunkLen)) / BYTE_PER_BLOCK;
if (nBlocksToInit > BLKS_PER_EXTENT)
nBlocksToInit = BLKS_PER_EXTENT; // don't init > 1 full extent
if (nBlocksToInit > 0)
{
uint64_t emptyVal = fDbFile.getEmptyRowValue( colType, colWidth );
rc = fDbFile.reInitPartialColumnExtent( pFile,
(chunkPtrs[chunkIndex].first + restoredChunkLen),
nBlocksToInit,
emptyVal,
colWidth );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error clearing HWM column extent from DB for"
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
}
// Drop off any trailing pointers (that point beyond the last block).
// Watch for the special case where we are restoring a db file as an
// empty file (chunkindex=0 and restoredChunkLen=0); in this case we
// just restore the first pointer (set to 8192).
fCompressor.setBlockCount( hdrs, (startOffsetBlk + nBlocks) );
std::vector<uint64_t> newPtrs;
if ((chunkIndex > 0) || (restoredChunkLen > 0))
{
for (unsigned int i=0; i<=chunkIndex; i++)
{
newPtrs.push_back( chunkPtrs[i].first );
}
}
newPtrs.push_back( chunkPtrs[chunkIndex].first + restoredChunkLen );
fCompressor.storePtrs( newPtrs, hdrs );
rc = fDbFile.writeHeaders( pFile, hdrs );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error writing compressed column headers to DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// Finally, we truncate the data base column segment file
rc = fDbFile.truncateFile( pFile, fileSizeBytes );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error truncating compressed column extents from DB for" <<
": OID-" << columnOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
} // end of (chunkIndex < chunkPtrs.size())
fDbFile.closeFile( pFile );
}
//------------------------------------------------------------------------------
// Load header pointer data for compressed column file.
//
// pFile - FILE ptr to be used in reading header data.
// hdrs - (out) Raw header data.
// chunkPtrs - (out) Chunk ptrs extracted from raw header data.
// errMsg - (out) Error message if applicable.
//------------------------------------------------------------------------------
int BulkRollbackFileCompressed::loadColumnHdrPtrs(
IDBDataFile* pFile,
char* hdrs,
CompChunkPtrList& chunkPtrs,
std::string& errMsg) const
{
// Read the header pointers
int rc = fDbFile.readHeaders( pFile, hdrs );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Header read error: " << ec.errorString(rc);
errMsg = oss.str();
return rc;
}
// Parse the header pointers
int rc1 = fCompressor.getPtrList( hdrs, chunkPtrs );
if (rc1 != 0)
{
rc = ERR_METADATABKUP_COMP_PARSE_HDRS;
WErrorCodes ec;
std::ostringstream oss;
oss << "Header parsing error (" << rc1 << "): " << ec.errorString(rc);
errMsg = oss.str();
return rc;
}
return NO_ERROR;
}
//------------------------------------------------------------------------------
// Reinitialize a dictionary segment extent (in the db file) to empty blocks,
// following the HWM. Remaining extents in the file are truncated.
// Also updates the header(s) as well.
//
// dStoreOID - OID of segment store file to be reinitialized
// dbRoot - DBRoot of segment file to be reinitialized
// partNum - Partition number of segment file to be reinitialized
// segNum - Segment number of segment file to be reinitialized
// startOffsetBlk - Starting block (after the HWM block), at which the file is
// to be reinitialized. Value is in raw data blocks.
// nBlocks - Number of blocks to be reinitialized
//------------------------------------------------------------------------------
void BulkRollbackFileCompressed::reInitTruncDctnryExtent(
OID dStoreOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks )
{
long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
std::ostringstream msgText1;
msgText1 << "Reinit HWM compressed dictionary store extent in db file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; rawOffset(bytes)-" << startOffset <<
"; rawFreeBlks-" << nBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, dStoreOID, msgText1.str() );
std::string segFile;
IDBDataFile* pFile = fDbFile.openFile(dStoreOID, dbRoot, partNum, segNum, segFile);
if (pFile == 0)
{
std::ostringstream oss;
oss << "Error opening compressed dictionary store segment file to "
"rollback extents from DB for" <<
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), ERR_FILE_OPEN );
}
char controlHdr[ IDBCompressInterface::HDR_BUF_LEN ];
CompChunkPtrList chunkPtrs;
uint64_t ptrHdrSize;
std::string errMsg;
int rc = loadDctnryHdrPtrs(pFile, controlHdr, chunkPtrs, ptrHdrSize,errMsg);
if (rc != NO_ERROR)
{
std::ostringstream oss;
oss << "Error reading compressed dctnry ptr headers from DB for" <<
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << errMsg;
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// Locate the chunk containing the last block we intend to keep
unsigned int blockOffset = startOffsetBlk - 1;
unsigned int chunkIndex = 0;
unsigned int blkOffsetInChunk = 0;
fCompressor.locateBlock( blockOffset, chunkIndex, blkOffsetInChunk );
if (chunkIndex < chunkPtrs.size())
{
// Read backup copy of HWM chunk and restore it's contents
uint64_t restoredChunkLen = 0;
uint64_t restoredFileSize = 0;
rc = restoreHWMChunk(pFile, dStoreOID, partNum, segNum,
chunkPtrs[chunkIndex].first,
restoredChunkLen, restoredFileSize, errMsg);
if (rc == ERR_FILE_NOT_EXIST)
{
std::ostringstream msgText3;
msgText3 << "No restore needed to Compressed dictionary file" <<
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, dStoreOID, msgText3.str() );
fDbFile.closeFile( pFile );
return;
}
if (rc != NO_ERROR)
{
std::ostringstream oss;
oss << "Error restoring HWM chunk for" <<
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; blkoff-" << blockOffset <<
"; " << errMsg;
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// nBlocks is based on full extents, but if database file only has an
// abbreviated extent, then we reset nBlocks to reflect the file size.
// (Unlike column files which only employ an abbreviated extent for the
// 1st extent in part0, seg0, all store files start with abbrev extent)
bool bAbbreviatedExtent = false;
const uint32_t PSEUDO_COL_WIDTH = 8; // simulated col width for dctnry
long long nBytesInAbbrevExtent = INITIAL_EXTENT_ROWS_TO_DISK *
PSEUDO_COL_WIDTH;
if (startOffset <= nBytesInAbbrevExtent)
{
nBlocks = (nBytesInAbbrevExtent-startOffset) / BYTE_PER_BLOCK;
bAbbreviatedExtent = true;
}
long long fileSizeBytes = restoredFileSize;
std::ostringstream msgText2;
msgText2 << "HWM compressed dictionary file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum;
if (bAbbreviatedExtent) // log adjusted nBlock count for abbrev extent
msgText2 << "; rawFreeBlks-" << nBlocks << " (abbrev)";
msgText2 << "; restoredChunk-" << restoredChunkLen << " bytes" <<
"; truncated to " << fileSizeBytes << " bytes";
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, dStoreOID, msgText2.str() );
// Initialize the remainder of the extent after the HWM chunk
// Just doing an ftruncate() reinits the file to 0's, which may or may
// not actually reserve disk space if ftruncate is growing the file.
// So reinit the blocks by calling reInitPartialDctnryExtent() to help
// avoid disk fragmentation. Be careful not to init > 1 extent, be-
// cause that is the limit on what that function was intended to do.
const unsigned BLKS_PER_EXTENT =
(BRMWrapper::getInstance()->getExtentRows() * PSEUDO_COL_WIDTH) /
BYTE_PER_BLOCK;
long long nBlocksToInit = (fileSizeBytes -
(chunkPtrs[chunkIndex].first + restoredChunkLen)) / BYTE_PER_BLOCK;
if (nBlocksToInit > BLKS_PER_EXTENT)
nBlocksToInit = BLKS_PER_EXTENT; // don't init > 1 full extent
if (nBlocksToInit > 0)
{
rc = fDbFile.reInitPartialDctnryExtent( pFile,
(chunkPtrs[chunkIndex].first + restoredChunkLen),
nBlocksToInit,
fDctnryHdr,
DCTNRY_HEADER_SIZE );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error clearing HWM dictionary store extent from DB for"
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
}
// Drop off any trailing pointers (that point beyond the last block).
// Watch for the special case where we are restoring a db file as an
// empty file (chunkindex=0 and restoredChunkLen=0); in this case we
// just restore the first pointer (set to 8192).
fCompressor.setBlockCount( controlHdr, (startOffsetBlk + nBlocks) );
std::vector<uint64_t> newPtrs;
if ((chunkIndex > 0) || (restoredChunkLen > 0))
{
for (unsigned int i=0; i<=chunkIndex; i++)
{
newPtrs.push_back( chunkPtrs[i].first );
}
}
newPtrs.push_back( chunkPtrs[chunkIndex].first + restoredChunkLen );
char* pointerHdr = new char[ptrHdrSize];
fCompressor.storePtrs( newPtrs, pointerHdr, ptrHdrSize );
rc = fDbFile.writeHeaders( pFile, controlHdr, pointerHdr, ptrHdrSize );
delete[] pointerHdr;
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error writing compressed dictionary headers to DB for" <<
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
// Finally, we truncate the data base dictionary store segment file
rc = fDbFile.truncateFile( pFile, fileSizeBytes );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error truncating compressed dictionary store extents "
"from DB file for" <<
": OID-" << dStoreOID <<
"; DbRoot-" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << ec.errorString(rc);
fDbFile.closeFile( pFile );
throw WeException( oss.str(), rc );
}
} // end of (chunkIndex < chunkPtrs.size())
fDbFile.closeFile( pFile );
}
//------------------------------------------------------------------------------
// Load header pointer data for compressed dictionary file.
//
// pFile - FILE ptr to be used in reading header data.
// controlHdr- (out) Raw data from control header.
// chunkPtrs - (out) Chunk ptrs extracted from raw header data.
// ptrHdrSize- (out) Size of pointer header.
// errMsg - (out) Error message if applicable.
//------------------------------------------------------------------------------
int BulkRollbackFileCompressed::loadDctnryHdrPtrs(
IDBDataFile* pFile,
char* controlHdr,
CompChunkPtrList& chunkPtrs,
uint64_t& ptrHdrSize,
std::string& errMsg) const
{
int rc = fDbFile.readFile(
pFile, (unsigned char*)controlHdr, IDBCompressInterface::HDR_BUF_LEN);
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Control header read error: " << ec.errorString(rc);
errMsg = oss.str();
return rc;
}
int rc1 = fCompressor.verifyHdr( controlHdr );
if (rc1 != 0)
{
rc = ERR_METADATABKUP_COMP_VERIFY_HDRS;
WErrorCodes ec;
std::ostringstream oss;
oss << "Control header verify error (" << rc1 << "): " <<
ec.errorString(rc);
errMsg = oss.str();
return rc;
}
uint64_t hdrSize = fCompressor.getHdrSize(controlHdr);
ptrHdrSize = hdrSize - IDBCompressInterface::HDR_BUF_LEN;
char* pointerHdr = new char[ptrHdrSize];
rc = fDbFile.readFile(pFile, (unsigned char*)pointerHdr, ptrHdrSize);
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Pointer header read error: " << ec.errorString(rc);
errMsg = oss.str();
delete[] pointerHdr;
return rc;
}
// Parse the header pointers
rc1 = fCompressor.getPtrList( pointerHdr, ptrHdrSize, chunkPtrs );
delete[] pointerHdr;
if (rc1 != 0)
{
rc = ERR_METADATABKUP_COMP_PARSE_HDRS;
WErrorCodes ec;
std::ostringstream oss;
oss << "Pointer header parsing error (" << rc1 << "): " <<
ec.errorString(rc);
errMsg = oss.str();
return rc;
}
return NO_ERROR;
}
//------------------------------------------------------------------------------
// Restore the HWM chunk back to the contents saved in the backup file.
//
// pFile - FILE* to segment file being reinitialized
// columnOID - OID of segment file to be reinitialized
// partNum - Partition num of seg file to reinitialize
// segNum - Segment num of seg file to reinitialize
// fileOffsetByteForRestoredChunk - Offset to pFile where restored chunk is to
// be written
// restoredChunkLen (out) - Length of restored chunk (in bytes)
// restoredFileSize (out) - Size of file (in bytes) when backup was made
// errMsg (out) - Error msg if error returned
//------------------------------------------------------------------------------
int BulkRollbackFileCompressed::restoreHWMChunk(
IDBDataFile* pFile,
OID columnOID,
uint32_t partNum,
uint32_t segNum,
uint64_t fileOffsetByteForRestoredChunk,
uint64_t& restoredChunkLen,
uint64_t& restoredFileSize,
std::string& errMsg)
{
restoredChunkLen = 0;
restoredFileSize = 0;
// Open the backup HWM chunk file
std::ostringstream oss;
oss << "/" << columnOID << ".p" << partNum << ".s" << segNum;
std::string bulkRollbackSubPath( fMgr->getMetaFileName() );
bulkRollbackSubPath += DATA_DIR_SUFFIX;
bulkRollbackSubPath += oss.str();
if ( !IDBPolicy::exists( bulkRollbackSubPath.c_str() ) )
{
std::ostringstream oss;
oss << "Backup file does not exist: " << bulkRollbackSubPath;
errMsg = oss.str();
return ERR_FILE_NOT_EXIST;
}
IDBDataFile* backupFile = IDBDataFile::open(
IDBPolicy::getType( bulkRollbackSubPath.c_str(), IDBPolicy::WRITEENG ),
bulkRollbackSubPath.c_str(),
"rb",
0,
pFile->colWidth() );
if (!backupFile)
{
int errrc = errno;
std::string eMsg;
Convertor::mapErrnoToString(errrc, eMsg);
std::ostringstream oss;
oss << "Error opening backup file " <<
bulkRollbackSubPath << "; " << eMsg;
errMsg = oss.str();
return ERR_METADATABKUP_COMP_OPEN_BULK_BKUP;
}
// Read the chunk length and file size
uint64_t sizeHdr[2];
size_t bytesRead = readFillBuffer(backupFile, (char*)sizeHdr,
sizeof(uint64_t)*2);
if (bytesRead != sizeof(uint64_t)*2)
{
int errrc = errno;
std::string eMsg;
Convertor::mapErrnoToString(errrc, eMsg);
std::ostringstream oss;
oss << "Error reading chunk length from backup file " <<
bulkRollbackSubPath << "; " << eMsg;
errMsg = oss.str();
delete backupFile;
return ERR_METADATABKUP_COMP_READ_BULK_BKUP;
}
restoredChunkLen = sizeHdr[0];
restoredFileSize = sizeHdr[1];
// Position the destination offset in the DB file
int rc = fDbFile.setFileOffset(pFile, fileOffsetByteForRestoredChunk,
SEEK_SET);
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error setting column file offset" <<
"; offset-" << fileOffsetByteForRestoredChunk <<
"; " << ec.errorString(rc);
errMsg = oss.str();
delete backupFile;
return rc;
}
// Copy backup version of chunk back to DB, unless chunk length is 0
// in which case we have nothing to copy.
if (restoredChunkLen > 0)
{
// Read the HWM chunk to be restored
unsigned char* chunk = new unsigned char[restoredChunkLen];
boost::scoped_array<unsigned char> scopedChunk( chunk );
bytesRead = readFillBuffer(backupFile, (char*)chunk, restoredChunkLen);
if (bytesRead != restoredChunkLen)
{
int errrc = errno;
std::string eMsg;
Convertor::mapErrnoToString(errrc, eMsg);
std::ostringstream oss;
oss << "Error reading chunk data from backup file " <<
bulkRollbackSubPath <<
"; size-" << restoredChunkLen <<
": " << eMsg;
errMsg = oss.str();
delete backupFile;
return ERR_METADATABKUP_COMP_READ_BULK_BKUP;
}
// Write/restore the HWM chunk to the applicable database file
rc = fDbFile.writeFile(pFile, chunk, restoredChunkLen);
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error writing to column file" <<
"; offset-" << fileOffsetByteForRestoredChunk <<
"; bytes-" << restoredChunkLen <<
"; " << ec.errorString(rc);
errMsg = oss.str();
delete backupFile;
return rc;
}
}
delete backupFile;
return NO_ERROR;
}
//------------------------------------------------------------------------------
// Return true/false depending on whether the applicable backup chunk file can
// be found to restore a backed up compressed chunk back into a db file. If
// the backup file is not found, we assume that it's because one was not created
// and thus not needed.
//------------------------------------------------------------------------------
bool BulkRollbackFileCompressed::doWeReInitExtent( OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum) const
{
std::ostringstream oss;
oss << "/" << columnOID << ".p" << partNum << ".s" << segNum;
std::string bulkRollbackSubPath( fMgr->getMetaFileName() );
bulkRollbackSubPath += DATA_DIR_SUFFIX;
bulkRollbackSubPath += oss.str();
if ( !IDBPolicy::exists( bulkRollbackSubPath.c_str() ) )
{
return false;
}
return true;
}
//------------------------------------------------------------------------------
// Read requested number of bytes from the specified pFile into "buffer".
// Added this function as part of hdfs port, because IDBDataFile::read()
// may not return all the requested data in the first call to read().
//------------------------------------------------------------------------------
size_t BulkRollbackFileCompressed::readFillBuffer(
IDBDataFile* pFile,
char* buffer,
size_t bytesReq) const
{
char* pBuf = buffer;
ssize_t nBytes;
size_t bytesToRead = bytesReq;
size_t totalBytesRead = 0;
while (1)
{
nBytes = pFile->read(pBuf, bytesToRead);
if (nBytes > 0)
totalBytesRead += nBytes;
else
break;
if ((size_t)nBytes == bytesToRead)
break;
pBuf += nBytes;
bytesToRead = bytesToRead - (size_t)nBytes;
}
return totalBytesRead;
}
} //end of namespace

View File

@ -0,0 +1,156 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
* $Id: we_bulkrollbackfilecompressed.h 4726 2013-08-07 03:38:36Z bwilkinson $
*/
/** @file
* Contains class to restore compressed db files on behalf of BulkRollBackMgr.
*/
#ifndef WE_BULKROLLBACKFILECOMPRESSED_H_
#define WE_BULKROLLBACKFILECOMPRESSED_H_
#include <cstdio>
#include <cstring>
#include "we_define.h"
#include "we_type.h"
#include "we_bulkrollbackfile.h"
#include "idbcompress.h"
namespace WriteEngine
{
class BulkRollbackMgr;
//------------------------------------------------------------------------------
/** @brief Class used by BulkRollbackMgr to restore compressed db files.
*/
//------------------------------------------------------------------------------
class BulkRollbackFileCompressed : public BulkRollbackFile
{
public:
/** @brief BulkRollbackFile constructor
* @param mgr The controlling BulkRollbackMgr object.
*/
BulkRollbackFileCompressed(BulkRollbackMgr* mgr);
/** @brief BulkRollbackFile destructor
*/
virtual ~BulkRollbackFileCompressed();
/** @brief Do we reinit trailing blocks in the HWM extent for the specified
* segment file
*
* @param columnOID OID of the segment file in question
* @param dbRoot DBRoot for the segment file in question
* @param partNum Partition number for the segment file in question
* @param segNum Segment number for the segment file in question
*/
virtual bool doWeReInitExtent( OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum) const;
/** @brief Reinitialize the specified column segment file starting at
* startOffsetBlk, and truncate trailing extents.
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param startOffsetBlk Starting block offset where file is to be
* reinitialized
* @param nBlocks Number of blocks to be reinitialized
* @param colType Column type of the relevant segment file
* @param colWidth Width in bytes of column.
* @param restoreHwmChk Restore HWM chunk
*/
virtual void reInitTruncColumnExtent(OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks,
execplan::CalpontSystemCatalog::ColDataType colType,
uint32_t colWidth,
bool restoreHwmChk );
/** @brief Reinitialize the specified dictionary store segment file starting
* at startOffsetBlk, and truncate trailing extents.
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param startOffsetBlk Starting block offset where file is to be
* reinitialized
* @param nBlocks Number of blocks to be reinitialized
*/
virtual void reInitTruncDctnryExtent(OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks );
/** @brief Truncate the specified segment file to a specified num of bytes
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param fileSizeBlocks Number of blocks to retain in the file
*/
virtual void truncateSegmentFile( OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long filesSizeBlocks );
private:
// Disable unnecessary copy constructor and assignment operator
BulkRollbackFileCompressed(const BulkRollbackFileCompressed& rhs);
BulkRollbackFileCompressed& operator=(const BulkRollbackFileCompressed& rhs);
size_t readFillBuffer ( IDBDataFile* pFile,
char* buffer,
size_t bytesReq) const;
int restoreHWMChunk ( IDBDataFile* pFile,
OID columnOID,
uint32_t partNum,
uint32_t segNum,
uint64_t fileOffsetByteForRestoredChunk,
uint64_t& restoredChunkLen,
uint64_t& restoredFileSize,
std::string& errMsg );
int loadColumnHdrPtrs ( IDBDataFile* pFile,
char* hdrs,
compress::CompChunkPtrList& chunkPtrs,
std::string& errMsg) const;
int loadDctnryHdrPtrs ( IDBDataFile* pFile,
char* controlHdr,
compress::CompChunkPtrList& chunkPtrs,
uint64_t& ptrHdrSize,
std::string& errMsg ) const;
compress::IDBCompressInterface fCompressor;
};
} //end of namespace
#endif // WE_BULKROLLBACKFILECOMPRESSED_H_

View File

@ -0,0 +1,284 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
#include "we_bulkrollbackfilecompressedhdfs.h"
#include <sstream>
#include <boost/scoped_array.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/convenience.hpp>
#include "we_define.h"
#include "we_fileop.h"
#include "we_bulkrollbackmgr.h"
#include "we_confirmhdfsdbfile.h"
#include "we_convertor.h"
#include "messageids.h"
#include "IDBDataFile.h"
#include "IDBPolicy.h"
using namespace idbdatafile;
using namespace compress;
using namespace execplan;
namespace
{
const char* DATA_DIR_SUFFIX = "_data";
const char* OLD_FILE_SUFFIX = ".old_bulk";
}
namespace WriteEngine
{
//------------------------------------------------------------------------------
// BulkRollbackFileCompressedHdfs constructor
//------------------------------------------------------------------------------
BulkRollbackFileCompressedHdfs::BulkRollbackFileCompressedHdfs(
BulkRollbackMgr* mgr) :
BulkRollbackFile(mgr)
{
}
//------------------------------------------------------------------------------
// BulkRollbackFileCompressedHdfs destructor
//------------------------------------------------------------------------------
BulkRollbackFileCompressedHdfs::~BulkRollbackFileCompressedHdfs()
{
}
//------------------------------------------------------------------------------
// Truncate the specified database segment file to the extent specified by
// the given file offset. Also updates the header(s) as well.
//
// columnOID - OID of segment file to be truncated
// dbRoot - DBRoot of segment file to be truncated
// partNum - Partition number of segment file to be truncated
// segNum - Segment number of segment file to be truncated
// fileSizeBlocks - Number of raw data blocks to be left in the file.
// Remainder of file is to be truncated.
//------------------------------------------------------------------------------
void BulkRollbackFileCompressedHdfs::truncateSegmentFile(
OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long fileSizeBlocks )
{
std::ostringstream msgText;
msgText << "Truncating compressed HDFS column file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; rawTotBlks-" << fileSizeBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText.str() );
restoreFromBackup( "column", columnOID, dbRoot, partNum, segNum );
}
//------------------------------------------------------------------------------
// Reinitialize a column segment extent (in the db file) to empty values,
// following the HWM. Remaining extents in the file are truncated.
// Also updates the header(s) as well.
//
// columnOID - OID of segment file to be reinitialized
// dbRoot - DBRoot of segment file to be reinitialized
// partNum - Partition number of segment file to be reinitialized
// segNum - Segment number of segment file to be reinitialized
// startOffsetBlk - File offset (after the HWM block), at which the file is
// to be reinitialized. Value is in raw data blocks.
// nBlocks - Number of blocks to be reinitialized
// colType - Data type of the applicable column
// colWidth - Width in bytes, of the applicable column
// restoreHwmChk - Specifies whether HWM chunk is to be restored.
//------------------------------------------------------------------------------
void BulkRollbackFileCompressedHdfs::reInitTruncColumnExtent(
OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks,
CalpontSystemCatalog::ColDataType colType,
uint32_t colWidth,
bool restoreHwmChk )
{
long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
std::ostringstream msgText;
msgText << "Reinit HWM compressed column extent in HDFS db file" <<
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; rawOffset(bytes)-"<< startOffset <<
"; rawFreeBlks-" << nBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, columnOID, msgText.str() );
restoreFromBackup( "column", columnOID, dbRoot, partNum, segNum );
}
//------------------------------------------------------------------------------
// Reinitialize a dictionary segment extent (in the db file) to empty blocks,
// following the HWM. Remaining extents in the file are truncated.
// Also updates the header(s) as well.
//
// dStoreOID - OID of segment store file to be reinitialized
// dbRoot - DBRoot of segment file to be reinitialized
// partNum - Partition number of segment file to be reinitialized
// segNum - Segment number of segment file to be reinitialized
// startOffsetBlk - Starting block (after the HWM block), at which the file is
// to be reinitialized. Value is in raw data blocks.
// nBlocks - Number of blocks to be reinitialized
//------------------------------------------------------------------------------
void BulkRollbackFileCompressedHdfs::reInitTruncDctnryExtent(
OID dStoreOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks )
{
long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
std::ostringstream msgText;
msgText << "Reinit HWM compressed dictionary store extent in HDFS db file"
": dbRoot-" << dbRoot <<
"; part#-" << partNum <<
"; seg#-" << segNum <<
"; rawOffset(bytes)-" << startOffset <<
"; rawFreeBlks-" << nBlocks;
fMgr->logAMessage( logging::LOG_TYPE_INFO,
logging::M0075, dStoreOID, msgText.str() );
restoreFromBackup( "dictionary store", dStoreOID, dbRoot, partNum, segNum );
}
//------------------------------------------------------------------------------
// For HDFS system, just always return true.
// Let ConfirmHdfsDbFile later determine when/if/how to restore from any
// existing backup file.
//------------------------------------------------------------------------------
bool BulkRollbackFileCompressedHdfs::doWeReInitExtent( OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum) const
{
return true;
}
//------------------------------------------------------------------------------
// Replace the currently specified db file with it's corresponding backup file.
// The backup file is a complete backup, not just a backup of a single chunk.
//
// The initial implementation for this function restored from a NNN.pNNN.sNNN
// file stored under the meta file directory.
// The latest implementation for this function restores from a FILENNN.cdf.tmp
// or FILENNN.cdf.orig file stored in the same OID directory as the FILENNN.cdf
// file.
// However, this function still looks for the first backup file (NNN.pNNN.sNNN)
// in case the user did not upgrade cleanly, and we have to restore using an
// old leftover backup file.
//------------------------------------------------------------------------------
void BulkRollbackFileCompressedHdfs::restoreFromBackup(const char* colType,
OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum)
{
// Construct file name for db file to be restored
char dbFileName[FILE_NAME_SIZE];
int rc = fDbFile.getFileName( columnOID, dbFileName,
dbRoot, partNum, segNum );
if (rc != NO_ERROR)
{
std::ostringstream oss;
oss << "Error restoring " << colType <<
" HDFS file for OID " << columnOID <<
"; Can't construct file name for DBRoot" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), rc );
}
// Construct file name for backup copy of db file
std::ostringstream ossFile;
ossFile << "/" << columnOID << ".p" << partNum << ".s" << segNum;
std::string backupFileName( fMgr->getMetaFileName() );
backupFileName += DATA_DIR_SUFFIX;
backupFileName += ossFile.str();
std::string dbFileNameTmp = dbFileName;
dbFileNameTmp += OLD_FILE_SUFFIX;
// For backwards compatibility...
// Restore from backup file used in initial HDFS release, in case the user
// upgraded without going down cleanly. In that case we might need to
// rollback using an old backup file left from previous release.
if ( IDBPolicy::exists(backupFileName.c_str()) )
{
// Rename current db file to make room for restored file
rc = IDBPolicy::rename( dbFileName, dbFileNameTmp.c_str() );
if (rc != 0)
{
std::ostringstream oss;
oss << "Error restoring " << colType <<
" HDFS file for OID " << columnOID <<
"; Can't move old file for DBRoot" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), ERR_COMP_RENAME_FILE );
}
// Rename backup file to replace current db file
rc = IDBPolicy::rename( backupFileName.c_str(), dbFileName );
if (rc != 0)
{
std::ostringstream oss;
oss << "Error restoring " << colType <<
" HDFS file for OID " << columnOID <<
"; Can't rename backup file for DBRoot" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum;
throw WeException( oss.str(), ERR_METADATABKUP_COMP_RENAME );
}
// Delete db file we just replaced with backup
IDBPolicy::remove( dbFileNameTmp.c_str() );
}
else // Restore from HDFS temp swap backup file; This is the normal case
{
std::string errMsg;
ConfirmHdfsDbFile confirmHdfs;
rc = confirmHdfs.endDbFileChange( std::string("tmp"),
dbFileName,
false,
errMsg);
if (rc != 0)
{
std::ostringstream oss;
oss << "Error restoring " << colType <<
" HDFS file for OID " << columnOID <<
"; DBRoot" << dbRoot <<
"; partition-" << partNum <<
"; segment-" << segNum <<
"; " << errMsg;
throw WeException( oss.str(), rc );
}
}
}
} //end of namespace

View File

@ -0,0 +1,139 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/** @file
* Class to restore compressed hdfs db files on behalf of BulkRollBackMgr.
*/
#ifndef WE_BULKROLLBACKFILECOMPRESSEDHDFS_H_
#define WE_BULKROLLBACKFILECOMPRESSEDHDFS_H_
#include <cstdio>
#include <cstring>
#include "we_define.h"
#include "we_type.h"
#include "we_bulkrollbackfile.h"
namespace WriteEngine
{
class BulkRollbackMgr;
//------------------------------------------------------------------------------
/** @brief Class used by BulkRollbackMgr to restore compressed hdfs db files.
*
* BulkRollbackFileCompressed is used by non-hdfs system to restore a backup
* of the hwm compressed chunk.
* BulkRollbackFileCompressedHdfs is used by hdfs system to restore a backup
* of the entire hwm compressed db file.
*/
//------------------------------------------------------------------------------
class BulkRollbackFileCompressedHdfs : public BulkRollbackFile
{
public:
/** @brief BulkRollbackFile constructor
* @param mgr The controlling BulkRollbackMgr object.
*/
BulkRollbackFileCompressedHdfs(BulkRollbackMgr* mgr);
/** @brief BulkRollbackFile destructor
*/
virtual ~BulkRollbackFileCompressedHdfs();
/** @brief Do we reinit trailing blocks in the HWM extent for the specified
* segment file
*
* @param columnOID OID of the segment file in question
* @param dbRoot DBRoot for the segment file in question
* @param partNum Partition number for the segment file in question
* @param segNum Segment number for the segment file in question
*/
virtual bool doWeReInitExtent(OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum) const;
/** @brief Reinitialize the specified column segment file starting at
* startOffsetBlk, and truncate trailing extents.
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param startOffsetBlk Starting block offset where file is to be
* reinitialized
* @param nBlocks Number of blocks to be reinitialized
* @param colType Column type of the relevant segment file
* @param colWidth Width in bytes of column.
* @param restoreHwmChk Restore HWM chunk
*/
virtual void reInitTruncColumnExtent(OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks,
execplan::CalpontSystemCatalog::ColDataType colType,
uint32_t colWidth,
bool restoreHwmChk );
/** @brief Reinitialize the specified dictionary store segment file starting
* at startOffsetBlk, and truncate trailing extents.
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param startOffsetBlk Starting block offset where file is to be
* reinitialized
* @param nBlocks Number of blocks to be reinitialized
*/
virtual void reInitTruncDctnryExtent(OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long startOffsetBlk,
int nBlocks );
/** @brief Truncate the specified segment file to a specified num of bytes
* @param columnOID OID of the relevant segment file
* @param dbRoot DBRoot of the relevant segment file
* @param partNum Partition number of the relevant segment file
* @param segNum Segment number of the relevant segment file
* @param fileSizeBlocks Number of blocks to retain in the file
*/
virtual void truncateSegmentFile(OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
long long filesSizeBlocks );
private:
// Disable unnecessary copy constructor and assignment operator
BulkRollbackFileCompressedHdfs(const BulkRollbackFileCompressedHdfs& rhs);
BulkRollbackFileCompressedHdfs& operator=(
const BulkRollbackFileCompressedHdfs& rhs);
void restoreFromBackup(const char* colType,
OID columnOID,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum );
};
} //end of namespace
#endif // WE_BULKROLLBACKFILECOMPRESSEDHDFS_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
* $Id: we_bulkrollbackmgr.h 4726 2013-08-07 03:38:36Z bwilkinson $
*/
/** @file
* Contains class to clear a database table lock, and rolls back extents
* based on HWM meta data saved by a bulk load.
*/
#ifndef WE_BULKROLLBACKMGR_H_
#define WE_BULKROLLBACKMGR_H_
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <boost/thread/mutex.hpp>
#endif
#include <set>
#include <string>
#include <sstream>
#include <vector>
#include "we_type.h"
#include "messagelog.h"
#include "messageobj.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
namespace WriteEngine
{
class Log;
class BulkRollbackFile;
//------------------------------------------------------------------------------
/** @brief Class to clear a database table lock, and rolls back extents
* based on HWM meta data saved by a bulk load.
*/
//------------------------------------------------------------------------------
class BulkRollbackMgr
{
enum BulkRollbackVersion
{
BULK_RB_VERSION_OTHER,
BULK_RB_VERSION3 = 3,
BULK_RB_VERSION4 = 4
};
public:
/**
* @brief BulkRollbackMgr constructor
* @param tableOID table to be rolled back.
* @param lockID Table lock id of the table to be rolled back.
* Currently used for logging only.
* @param tableName name of table associated with tableOID.
* Currently used for logging only.
* @param applName application that is driving this bulk rollback.
* Currently used for logging only.
*/
EXPORT BulkRollbackMgr(OID tableOID,
uint64_t lockID,
const std::string& tableName,
const std::string& applName,
Log* logger=0);
/**
* @brief BulkRollbackMgr destructor
*/
EXPORT ~BulkRollbackMgr( ) { closeMetaDataFile ( ); }
/**
* @brief Clear table lock and rollback extents for fTableOID
* @param keepMetaFile controls whether the meta data file is deleted
* @return NO_ERROR upon success
*/
EXPORT int rollback ( bool keepMetaFile );
/**
* @brief Accessor to any error msg related to a bad return code.
* @return error message if rollback rejected or failed.
*/
const std::string& getErrorMsg( ) const { return fErrorMsg; }
/**
* @brief Accessor to the name of the meta file we are processing
*/
const std::string& getMetaFileName() const { return fMetaFileName; }
/**
* @brief Mutator to enable/disable debug logging to console.
*/
const void setDebugConsole ( bool debug ) { fDebugConsole = debug; }
/**
* @brief Log the specified message.
* @param logType type of message to be logged
* @param msgId message id to be used
* @param columnOID column OID
* @param text message text to be logged
*/
void logAMessage ( logging::LOG_TYPE logType, //log a message
logging::Message::MessageID msgId,
OID columnOID,
const std::string& text );
/**
* @brief Standalone utility that can be used to delete the bulk rollback
* meta data files. Caution: this function can throw an exception.
* @param tableOID Bulk rollback files for this table are to be deleted
*/
EXPORT static void deleteMetaFile( OID tableOID );
/*
* @brief Get list of segment file numbers found in dirName directory
* @param dirName Directory path to be searched
* @param bIncludeAlternateSegFileNames Include *.orig and *.tmp in search
* @param segList List of segment files found in dirName
* @param errMsg Error msg if return code is not NO_ERROR
*/
EXPORT static int getSegFileList( const std::string& dirName,
bool bIncludeAlternateSegFileNames,
std::vector<uint32_t>& segList,
std::string& errMsg );
private:
// Declare but don't define copy constructor and assignment operator
BulkRollbackMgr(const BulkRollbackMgr& rhs);
BulkRollbackMgr& operator=(const BulkRollbackMgr& rhs);
// Structure used to store info for the list of dictionary store
// segment files in the last partition.
struct RollbackData
{
uint32_t fDbRoot;
uint32_t fPartNum;
uint32_t fSegNum;
HWM fHwm;
bool fWithHwm;
};
void createFileDeletionEntry( OID columnOID,
bool fileTypeFlag,
uint32_t dbRoot,
uint32_t partNum,
uint32_t segNum,
const std::string& segFileName );
void deleteColumn1Extents ( const char* inBuf ); // delete col extents
void deleteColumn1ExtentsV3(const char* inBuf );
void deleteColumn1ExtentsV4(const char* inBuf );
void deleteColumn2Extents ( const char* inBuf ); // delete col extents
void deleteColumn2ExtentsV3(const char* inBuf );
void deleteColumn2ExtentsV4(const char* inBuf );
void deleteDbFiles ( ); // delete DB files waiting to be deleted
void deleteDctnryExtents ( ); // delete dictionary store extents
void deleteDctnryExtentsV3( );
void deleteDctnryExtentsV4( );
void deleteExtents ( std::istringstream& metaDataStream );
// function that drives extent deletion
void readMetaDataRecDctnry(const char* inBuf );//read meta-data dct rec
void deleteSubDir ( const std::string& metaFileName ); // delete
// subdirectory used for backup chunks
EXPORT void closeMetaDataFile ( ); // close a metafile
void deleteMetaDataFiles ( ); // delete metafiles
int metaDataFileExists ( bool& exists ); // does meta-data file exists
BulkRollbackFile* makeFileRestorer(int compressionType);
bool openMetaDataFile ( uint16_t dbRoot, // open a metadata file
std::istringstream& metaDataStream );
void validateAllMetaFilesExist(const std::vector<uint16_t>& dbRoots) const;
// Data members
OID fTableOID; // table to be rolled back
uint64_t fLockID; // unique lock ID associated with table lock
std::string fTableName; // name of table associated with fTableOID
uint32_t fProcessId; // pid associated with current table lock
std::string fProcessName; // processName associated with fProcessId
IDBDataFile* fMetaFile; // current meta data file we are reading
std::string fMetaFileName;// name of current meta data file
std::vector<std::string> fMetaFileNames; // all relevant meta data files
std::string fErrorMsg;
unsigned char fDctnryHdr[DCTNRY_HEADER_SIZE]; // empty dctnry store blk
// Dictionary store extents for an OID are read in and managed as a
// group. The following data members are used to collect this info.
OID fPendingDctnryStoreOID;// Dctnry OID of pending dctnry extents
uint32_t fPendingDctnryStoreDbRoot; // DbRoot of pending dctnry extents
int fPendingDctnryStoreCompressionType; // Dctnry compression type
std::vector<RollbackData> fPendingDctnryExtents;
std::set<OID> fAllColDctOIDs; // List of all affected col and dctnry OIDS
// List of DB Files to be deleted. Files are deleted in reverse order.
std::vector<File> fPendingFilesToDelete;
logging::MessageLog fSysLogger; // Used for syslogging
bool fDebugConsole; // control debug logging to console
Log* fLog; // optional logger object
std::string fApplName; // application initiating the bulk rollback
int fVersion; // version of meta data file being read
};
} //end of namespace
#undef EXPORT
#endif // WE_BULKROLLBACKMGR_H_

View File

@ -0,0 +1,418 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/******************************************************************************************
* $Id: we_cache.cpp 33 2006-10-30 13:45:13Z wzhou $
*
******************************************************************************************/
/** @file */
#include <we_cache.h>
using namespace std;
namespace WriteEngine
{
CacheControl* Cache::m_cacheParam = NULL;
FreeBufList* Cache::m_freeList = NULL;
CacheMap* Cache::m_lruList = NULL;
CacheMap* Cache::m_writeList = NULL;
#ifdef _MSC_VER
__declspec(dllexport)
#endif
bool Cache::m_useCache = false;
/***********************************************************
* DESCRIPTION:
* Clear all list and free memory
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
void Cache::clear()
{
CacheMapIt it;
BlockBuffer* block;
size_t i;
// free list
if( m_freeList != NULL ) {
for( i = 0; i < m_freeList->size(); i++ ) {
block = m_freeList->at(i);
block->clear();
}
}
// LRU list
if( m_lruList != NULL ) {
for( it = m_lruList->begin(); it != m_lruList->end(); it++ ) {
block = it->second;
block->clear();
m_freeList->push_back( block );
}
m_lruList->clear();
}
// Write list
if( m_writeList != NULL ) {
for( it = m_writeList->begin(); it != m_writeList->end(); it++ ) {
block = it->second;
block->clear();
m_freeList->push_back( block );
}
m_writeList->clear();
}
}
/***********************************************************
* DESCRIPTION:
* Flush write cache
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
const int Cache::flushCache()
{
bool bHasReadBlock = false;
BlockBuffer* curBuf;
// add lock here
if( m_lruList && m_lruList->size() > 0 ) {
bHasReadBlock = true;
for( CacheMapIt it = m_lruList->begin(); it != m_lruList->end(); it++ ) {
curBuf = it->second;
curBuf->clear();
m_freeList->push_back( curBuf );
}
m_lruList->clear();
}
// must write to disk first
if( m_writeList && m_writeList->size() > 0 ) {
if( !bHasReadBlock )
for( CacheMapIt it = m_writeList->begin(); it != m_writeList->end(); it++ ) {
curBuf = it->second;
curBuf->clear();
m_freeList->push_back( curBuf );
}
else
for( CacheMapIt it = m_writeList->begin(); it != m_writeList->end(); it++ ) {
curBuf = it->second;
(*curBuf).block.dirty = false;
processCacheMap( m_lruList, curBuf, INSERT );
}
m_writeList->clear();
} // end of if( m_writeList->size()
// add unlock here
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Free memory
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
void Cache::freeMemory()
{
CacheMapIt it;
BlockBuffer* block;
size_t i;
// free list
if( m_freeList != NULL ) {
for( i = 0; i < m_freeList->size(); i++ ) {
block = m_freeList->at(i);
block->freeMem();
delete block;
}
m_freeList->clear();
delete m_freeList;
m_freeList = NULL;
}
// LRU list
if( m_lruList != NULL ) {
for( it = m_lruList->begin(); it != m_lruList->end(); it++ ) {
block = it->second;
block->freeMem();
delete block;
}
m_lruList->clear();
delete m_lruList;
m_lruList = NULL;
}
// Write list
if( m_writeList != NULL ) {
for( it = m_writeList->begin(); it != m_writeList->end(); it++ ) {
block = it->second;
block->freeMem();
delete block;
}
m_writeList->clear();
delete m_writeList;
m_writeList = NULL;
}
// param
if( m_cacheParam != NULL ) {
delete m_cacheParam;
m_cacheParam = NULL;
}
}
/***********************************************************
* DESCRIPTION:
* get a list size
* PARAMETERS:
* listType - List type
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
const int Cache::getListSize( const CacheListType listType )
{
int size = 0;
if( !m_useCache )
return size;
switch( listType ) {
case FREE_LIST: size = m_freeList->size(); break;
case LRU_LIST: size = m_lruList->size(); break;
case WRITE_LIST:
default:
size = m_writeList->size(); break;
}
return size;
}
/***********************************************************
* DESCRIPTION:
* Init all parameters and list
* PARAMETERS:
* totalBlock - total blocks
* chkPoint - checkpoint interval
* pctFree - percentage free
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
void Cache::init( const int totalBlock, const int chkPoint, const int pctFree )
{
BlockBuffer* buffer;
if( m_cacheParam && m_freeList && m_lruList && m_writeList )
return;
m_cacheParam = new CacheControl();
m_cacheParam->totalBlock = totalBlock;
m_cacheParam->checkInterval = chkPoint;
m_cacheParam->pctFree = pctFree;
m_freeList = new FreeBufList();
m_lruList = new CacheMap();
m_writeList = new CacheMap();
for( int i = 0; i < m_cacheParam->totalBlock; i++ ) {
buffer = new BlockBuffer();
buffer->init();
m_freeList->push_back( buffer );
}
}
/***********************************************************
* DESCRIPTION:
* Insert a buffer to LRU list
* PARAMETERS:
* cb - Comm Block
* lbid - lbid value
* fbo - fbo
* buf - input buffer
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
const int Cache::insertLRUList( CommBlock& cb, const uint64_t lbid, const uint64_t fbo, const unsigned char* buf )
{
BlockBuffer* buffer;
vector<BlockBuffer*>::iterator it;
if( m_freeList->size() == 0 )
return ERR_FREE_LIST_EMPTY;
// make sure flush first if necessary
it = m_freeList->begin();
buffer = *it;
memcpy( (*buffer).block.data, buf, BYTE_PER_BLOCK );
(*buffer).listType = LRU_LIST;
(*buffer).block.lbid = lbid;
(*buffer).block.fbo = fbo;
(*buffer).block.dirty = false;
(*buffer).block.hitCount = 1;
(*buffer).cb.file.oid = cb.file.oid;
(*buffer).cb.file.pFile = cb.file.pFile;
RETURN_ON_ERROR( processCacheMap( m_lruList, buffer, INSERT ) );
m_freeList->erase( it );
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Load cache block
* PARAMETERS:
* key - Cache key
* buf - output buffer
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
const int Cache::loadCacheBlock( const CacheKey& key, unsigned char* buf )
{
BlockBuffer* buffer;
CacheMapIt iter;
iter = m_lruList->find( key );
if( iter != m_lruList->end() )
buffer = iter->second;
else {
iter = m_writeList->find( key );
if( iter != m_writeList->end() )
buffer = iter->second;
else
return ERR_CACHE_KEY_NOT_EXIST;
}
memcpy( buf, (*buffer).block.data, BYTE_PER_BLOCK );
(*buffer).block.hitCount++;
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Modify cache block
* PARAMETERS:
* key - Cache key
* buf - output buffer
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
const int Cache::modifyCacheBlock( const CacheKey& key, const unsigned char* buf )
{
BlockBuffer* buffer;
CacheMapIt iter;
iter = m_lruList->find( key );
if( iter != m_lruList->end() ) {
buffer = iter->second;
(*buffer).listType = WRITE_LIST;
(*buffer).block.dirty = true;
(*m_writeList)[key] = iter->second;
m_lruList->erase( iter );
}
else {
iter = m_writeList->find( key );
if( iter != m_writeList->end() )
buffer = iter->second;
else
return ERR_CACHE_KEY_NOT_EXIST;
}
memcpy( (*buffer).block.data, buf, BYTE_PER_BLOCK );
(*buffer).block.hitCount++;
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Print cache list
* PARAMETERS:
* none
* RETURN:
* none
***********************************************************/
void Cache::printCacheList()
{
BlockBuffer* buffer;
int i = 0;
if( !m_useCache )
return;
cout << "\nFree List has " << m_freeList->size() << " elements" << endl;
cout << "LRU List has " << m_lruList->size() << " elements" << endl;
for( CacheMapIt it = m_lruList->begin(); it != m_lruList->end(); it++ ) {
buffer = it->second;
cout << "\t[" << i++ << "] key=" << it->first << " listType=" << buffer->listType
<< " oid=" << (*buffer).cb.file.oid << " fbo=" << (*buffer).block.fbo
<< " dirty=" << (*buffer).block.dirty << " hitCount=" << (*buffer).block.hitCount << endl;
}
i = 0;
cout << "Write List has " << m_writeList->size() << " elements" << endl;
for( CacheMapIt it = m_writeList->begin(); it != m_writeList->end(); it++ ) {
buffer = it->second;
cout << "\t[" << i++ << "] key=" << it->first << " listType=" << buffer->listType
<< " oid=" << (*buffer).cb.file.oid << " fbo=" << (*buffer).block.fbo
<< " dirty=" << (*buffer).block.dirty << " hitCount=" << (*buffer).block.hitCount << endl;
}
}
/***********************************************************
* DESCRIPTION:
* Process a buffer in a cache map
* PARAMETERS:
* buffer - block buffer
* opType - insert or delete
* RETURN:
* NO_ERROR if success, other otherwise
***********************************************************/
const int Cache::processCacheMap( CacheMap* map, BlockBuffer* buffer, OpType opType )
{
RETURN_ON_NULL( buffer, ERR_NULL_BLOCK );
CacheMapIt iter;
CacheKey key = getCacheKey( buffer );
iter = map->find( key );
// only handle insert and delete
if( iter == map->end() ) {
if( opType == INSERT )
(*map)[key] = buffer;
else
return ERR_CACHE_KEY_NOT_EXIST;
}
else {
if( opType == INSERT )
return ERR_CACHE_KEY_EXIST;
else
map->erase( iter );
}
return NO_ERROR;
}
} //end of namespace

View File

@ -0,0 +1,190 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/******************************************************************************************
* $Id: we_cache.h 33 2006-10-30 13:45:13Z wzhou $
*
******************************************************************************************/
/** @file */
#ifndef _WE_CACHE_H_
#define _WE_CACHE_H_
#include <iostream>
#ifdef _MSC_VER
#include <unordered_map>
#else
#if __GNUC__ == 4 && __GNUC_MINOR__ < 2
#include <ext/hash_map>
#else
#include <tr1/unordered_map>
#endif
#endif
#include <map>
#include <we_obj.h>
#include <we_convertor.h>
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
typedef std::vector<BlockBuffer*> FreeBufList; /** @brief Free buffer list */
//typedef std::string CacheKey; /** @brief Key definition */
typedef uint64_t CacheKey; /** @brief Key definition */
//typedef std::map<CacheKey, BlockBuffer*, std::greater<CacheKey> > CacheMap; /** @brief Cache map */
//typedef CacheMap::iterator CacheMapIt; /** @brief CacheMap iterator */
template<class T>struct hashCacheKey{ };
template<> struct hashCacheKey<CacheKey>
{
size_t
operator()(CacheKey __x) const
{ return __x; }
};
struct eqCacheKey
{
bool operator() (const CacheKey k1, const CacheKey k2 ) const
{
return k1 == k2;
}
};
//typedef hash_map<Signature, TokenStruc, signatureHash<Signature>, eqSig> DCTNRYHASHMAP;
#if __GNUC__ == 4 && __GNUC_MINOR__ < 2
typedef __gnu_cxx::hash_map<CacheKey, BlockBuffer*, hashCacheKey<CacheKey>, eqCacheKey> CacheMap;
#else
typedef std::tr1::unordered_map<CacheKey, BlockBuffer*, hashCacheKey<CacheKey>, eqCacheKey> CacheMap;
#endif
//typedef __gnu_cxx::hash_map<CacheKey, BlockBuffer*> CacheMap;
typedef CacheMap::iterator CacheMapIt;
//typedef CacheMap LRUBufList; /** @brief Least Recent Used Buffer list */
//typedef CacheMap WriteBufList; /** @brief Write buffer list */
/** Class Cache */
class Cache
{
public:
/**
* @brief Constructor
*/
Cache() {}
/**
* @brief Default Destructor
*/
~Cache() {}
/**
* @brief Check whether cache key exists
*/
static const bool cacheKeyExist( CacheMap* map, const OID oid, const uint64_t lbid ) { CacheKey key = getCacheKey( oid, lbid ); return map->find(key) == map->end() ? false: true; }
static const bool cacheKeyExist( CacheMap* map, BlockBuffer* buffer ) { return cacheKeyExist( map, (*buffer).cb.file.oid, (*buffer).block.lbid ); }
static const bool cacheKeyExist( const OID oid, const uint64_t lbid ) { return cacheKeyExist( m_lruList, oid, lbid ) || cacheKeyExist( m_writeList, oid, lbid ); }
/**
* @brief Clear the buffer
*/
EXPORT static void clear();
/**
* @brief Free the buffer memory
*/
EXPORT static void freeMemory();
/**
* @brief Flush the write cache
*/
EXPORT static const int flushCache();
/**
* @brief Get the cache key
*/
static CacheKey getCacheKey( const OID oid, const uint64_t lbid ) { CacheKey key = lbid; /*Convertor::int2Str( oid ) + "|" + Convertor::int2Str(lbid)*/; return key; }
static CacheKey getCacheKey( const BlockBuffer* buffer ) { return getCacheKey( (*buffer).cb.file.oid, (*buffer).block.lbid ); }
EXPORT static const int getListSize( const CacheListType listType );
/**
* @brief Init the buffers
*/
EXPORT static void init( const int totalBlock, const int chkPoint, const int pctFree );
static void init() { init( DEFAULT_CACHE_BLOCK, DEFAULT_CHK_INTERVAL, DEFAULT_CACHE_PCT_FREE ); }
/**
* @brief Insert into LRU list
*/
EXPORT static const int insertLRUList( CommBlock& cb, const uint64_t lbid, const uint64_t fbo, const unsigned char* buf );
static const int insertLRUList( CommBlock& cb, const uint64_t lbid, const uint64_t fbo, const DataBlock& block ) { return insertLRUList( cb, lbid, fbo, block.data ); }
/**
* @brief Insert into Write list
*/
// static const int insertWriteList( const CacheKey& key );
/**
* @brief Load cache block to a buffer
*/
static const int loadCacheBlock( const CacheKey& key, DataBlock& block ) { return loadCacheBlock( key, block.data ); }
EXPORT static const int loadCacheBlock( const CacheKey& key, unsigned char* buf );
/**
* @brief Modify a cache block
*/
static const int modifyCacheBlock( const CacheKey& key, const DataBlock& block ) { return modifyCacheBlock( key, block.data ); }
EXPORT static const int modifyCacheBlock( const CacheKey& key, const unsigned char* buf );
/**
* @brief Print
*/
EXPORT static void printCacheMapList( const CacheMap* map );
EXPORT static void printCacheList();
/**
* @brief Insert/Delete an element in cache map
*/
EXPORT static const int processCacheMap( CacheMap* map, BlockBuffer* buffer, OpType opType );
// accessory
static const int getTotalBlock() { return m_cacheParam->totalBlock; }
static const bool getUseCache() { return m_useCache; }
static void setUseCache( const bool flag ) { m_useCache = flag; }
static CacheControl* m_cacheParam; // Cache parameters
static FreeBufList* m_freeList; // free buffer list
static CacheMap* m_lruList; // LRU buffer list
static CacheMap* m_writeList; // Write buffer list
#if defined(_MSC_VER) && !defined(WRITEENGINE_DLLEXPORT)
__declspec(dllimport)
#endif
EXPORT static bool m_useCache; // Use cache flag
private:
};
} //end of namespace
#undef EXPORT
#endif // _WE_CACHE_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,363 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id: we_chunkmanager.h 4726 2013-08-07 03:38:36Z bwilkinson $
/** @file */
#ifndef CHUNK_MANAGER_H
#define CHUNK_MANAGER_H
#include <cstdio>
#include <map>
#include <list>
#include <string>
#include <boost/scoped_array.hpp>
#include "we_type.h"
#include "we_typeext.h"
#include "we_define.h"
#include "idbcompress.h"
#include "IDBFileSystem.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
#ifdef _MSC_VER
#define WE_COMP_DBG(x) {}
#else
//#define IDB_COMP_DEBUG
#ifdef IDB_COMP_DEBUG
#define WE_COMP_DBG(x) {x}
#else
#define WE_COMP_DBG(x) {}
#endif
#endif
namespace logging
{
// use Logger (not we_log) for now.
class Logger;
}
namespace WriteEngine
{
// forward reference
class FileOp;
const int UNCOMPRESSED_CHUNK_SIZE = compress::IDBCompressInterface::UNCOMPRESSED_INBUF_LEN;
const int COMPRESSED_FILE_HEADER_UNIT = compress::IDBCompressInterface::HDR_BUF_LEN;
// assume UNCOMPRESSED_CHUNK_SIZE > 0xBFFF (49151), 8 * 1024 bytes padding
const int COMPRESSED_CHUNK_SIZE = compress::IDBCompressInterface::maxCompressedSize(UNCOMPRESSED_CHUNK_SIZE) + 64+3 + 8*1024;
const int BLOCKS_IN_CHUNK = UNCOMPRESSED_CHUNK_SIZE / BYTE_PER_BLOCK;
const int MAXOFFSET_PER_CHUNK = 511*BYTE_PER_BLOCK;
// chunk information
typedef int64_t ChunkId;
struct ChunkData
{
ChunkId fChunkId;
unsigned int fLenUnCompressed;
char fBufUnCompressed[UNCOMPRESSED_CHUNK_SIZE];
bool fWriteToFile;
ChunkData(ChunkId id = 0) : fChunkId(id), fLenUnCompressed(0), fWriteToFile(false) {}
bool operator < (const ChunkData& rhs) const { return fChunkId < rhs.fChunkId; }
};
// compressed DB file header information
struct CompFileHeader
{
char fHeaderData[COMPRESSED_FILE_HEADER_UNIT * 2];
char *fControlData;
char *fPtrSection;
boost::scoped_array<char> fLongPtrSectData;
CompFileHeader() :
fControlData(fHeaderData), fPtrSection(fHeaderData+COMPRESSED_FILE_HEADER_UNIT) {}
};
// unique ID of a DB file
struct FileID
{
FID fFid;
uint32_t fDbRoot;
uint32_t fPartition;
uint32_t fSegment;
FileID(FID f, uint32_t r, uint32_t p, uint32_t s) :
fFid(f), fDbRoot(r), fPartition(p), fSegment(s) {}
bool operator < (const FileID& rhs) const
{ return (
(fFid < rhs.fFid) ||
(fFid == rhs.fFid && fDbRoot < rhs.fDbRoot) ||
(fFid == rhs.fFid && fDbRoot == rhs.fDbRoot && fPartition < rhs.fPartition) ||
(fFid == rhs.fFid && fDbRoot == rhs.fDbRoot && fPartition == rhs.fPartition && fSegment < rhs.fSegment)); }
bool operator == (const FileID& rhs) const
{ return (
fFid == rhs.fFid && fDbRoot == rhs.fDbRoot && fPartition == rhs.fPartition && fSegment == rhs.fSegment); }
};
// compressed DB file information
class CompFileData
{
public:
CompFileData(const FileID& id, const FID& fid, const execplan::CalpontSystemCatalog::ColDataType colDataType, int colWidth) :
fFileID(id), fFid(fid), fColDataType(colDataType), fColWidth(colWidth), fDctnryCol(false),
fFilePtr(NULL), fIoBSize(0) {}
ChunkData* findChunk(int64_t cid) const;
protected:
FileID fFileID;
FID fFid;
execplan::CalpontSystemCatalog::ColDataType fColDataType;
int fColWidth;
bool fDctnryCol;
IDBDataFile* fFilePtr;
std::string fFileName;
CompFileHeader fFileHeader;
std::list<ChunkData*> fChunkList;
boost::scoped_array<char> fIoBuffer;
size_t fIoBSize;
friend class ChunkManager;
};
class ChunkManager
{
public:
// @brief constructor
EXPORT ChunkManager();
// @brief destructor
EXPORT virtual ~ChunkManager();
// @brief Retrieve a file pointer in the chunk manager.
// for column file
IDBDataFile* getFilePtr(const Column& column,
uint16_t root,
uint32_t partition,
uint16_t segment,
std::string& filename,
const char* mode,
int size,
bool useTmpSuffix) const;
// @brief Retrieve a file pointer in the chunk manager.
// for dictionary file
IDBDataFile* getFilePtr(const FID& fid,
uint16_t root,
uint32_t partition,
uint16_t segment,
std::string& filename,
const char* mode,
int size,
bool useTmpSuffix) const;
// @brief Create a compressed dictionary file with an appropriate header.
IDBDataFile* createDctnryFile(const FID& fid,
int64_t width,
uint16_t root,
uint32_t partition,
uint16_t segment,
const char* filename,
const char* mode,
int size);
// @brief Read a block from pFile at offset fbo.
// The data may copied from memory if the chunk it belongs to is already available.
int readBlock(IDBDataFile* pFile, unsigned char* readBuf, uint64_t fbo);
// @brief Save a block to a chunk in pFile.
// The block is not written to disk immediately, will be delayed until flush.
int saveBlock(IDBDataFile* pFile, const unsigned char* writeBuf, uint64_t fbo);
// @brief Write all active chunks to disk, and reset all repository.
EXPORT int flushChunks(int rc, const std::map<FID, FID> & columOids);
// @brief Reset all repository without writing anything to disk.
void cleanUp(const std::map<FID, FID> & columOids);
// @brief Expand an initial column, not dictionary, extent to a full extent.
int expandAbbrevColumnExtent(IDBDataFile* pFile, uint64_t emptyVal, int width);
// @brief Update column extent
int updateColumnExtent(IDBDataFile* pFile, int addBlockCount);
// @brief Update dictionary extent
int updateDctnryExtent(IDBDataFile* pFile, int addBlockCount);
// @brief Read in n continuous blocks to read buffer.
// for backing up blocks to version buffer
int readBlocks(IDBDataFile* pFile, unsigned char* readBuf, uint64_t fbo, size_t n);
// @brief Restore the data block at offset fbo from version buffer
// for rollback
int restoreBlock(IDBDataFile* pFile, const unsigned char* writeBuf, uint64_t fbo);
// @brief Retrieve the total block count of a DB file.
int getBlockCount(IDBDataFile* pFile);
// @brief Set FileOp pointer (for compression type, empty value, txnId, etc.)
void fileOp(FileOp* fileOp);
// @brief Control the number of active chunks being stored in memory
void setMaxActiveChunkNum(unsigned int maxActiveChunkNum)
{ fMaxActiveChunkNum = maxActiveChunkNum; }
// @brief Use this flag to avoid logging and backing up chunks, tmp files.
void setBulkFlag(bool isBulkLoad)
{ fIsBulkLoad = isBulkLoad; }
// @brief Use this flag to flush chunk when is full.
void setIsInsert(bool isInsert) { fIsInsert = isInsert; }
bool getIsInsert() { return fIsInsert; }
void setTransId(const TxnID& transId) { fTransId = transId; }
// @brief bug5504, Use non transactional DML for InfiniDB with HDFS
EXPORT int startTransaction(const TxnID& transId) const;
EXPORT int confirmTransaction(const TxnID& transId) const;
EXPORT int endTransaction(const TxnID& transId, bool success) const;
// @brief Use this flag to fix bad chunk.
void setFixFlag(bool isFix)
{ fIsFix = isFix; }
EXPORT int checkFixLastDictChunk(const FID& fid,
uint16_t root,
uint32_t partition,
uint16_t segment);
protected:
// @brief Retrieve pointer to a compressed DB file.
CompFileData* getFileData(const FID& fid,
uint16_t root,
uint32_t partition,
uint16_t segment,
std::string& filename,
const char* mode,
int size,
const execplan::CalpontSystemCatalog::ColDataType colDataType,
int colWidth,
bool useTmpSuffix,
bool dictnry = false) const;
// @brief Retrieve a chunk of pFile from disk.
int fetchChunkFromFile(IDBDataFile* pFile, int64_t id, ChunkData*& chunkData);
// @brief Compress a chunk and write it to file.
int writeChunkToFile(CompFileData* fileData, int64_t id);
int writeChunkToFile(CompFileData* fileData, ChunkData* chunkData);
// @brief Write the compressed data to file and log a recover entry.
int writeCompressedChunk(CompFileData* fileData, int64_t offset, int64_t size);
inline int writeCompressedChunk_(CompFileData* fileData, int64_t offset);
// @brief Write the file header to disk.
int writeHeader(CompFileData* fileData, int ln);
inline int writeHeader_(CompFileData* fileData, int ptrSecSize);
// @brief open a compressed DB file.
int openFile(CompFileData* fileData, const char* mode, int colWidth,
bool useTmpSuffix, int ln) const;
// @brief set offset in a compressed DB file from beginning.
int setFileOffset(IDBDataFile* pFile, const std::string& fileName, off64_t offset, int ln) const;
// @brief read from a compressed DB file.
int readFile(IDBDataFile* pFile, const std::string& fileName, void* buf, size_t size, int ln) const;
// @brief write to a compressed DB file.
int writeFile(IDBDataFile* pFile, const std::string& fileName, void* buf, size_t size, int ln) const;
// @brief Close a compressed DB file.
int closeFile(CompFileData* fileData);
// @brief Set empty values to a chunk.
void initializeColumnChunk(char* buf, CompFileData* fileData);
void initializeDctnryChunk(char* buf, int size);
// @brief Calculate the header size based on column width.
int calculateHeaderSize(int width);
// @brief Moving chunks as a result of expanding a chunk.
int reallocateChunks(CompFileData* fileData);
// @brief verify chunks in the file are OK
int verifyChunksAfterRealloc(CompFileData* fileData);
// @brief log a message to the syslog
void logMessage(int code, int level, int lineNum, int fromLine=-1) const;
void logMessage(const std::string& msg, int level) const;
// @brief Write a DML recovery log
int writeLog(TxnID txnId, std::string backUpFileType, std::string filename,
std::string &aDMLLogFileName, int64_t size=0, int64_t offset=0) const;
// @brief remove DML recovery logs
int removeBackups(TxnID txnId);
// @brief swap the src file to dest file
int swapTmpFile(const std::string& src, const std::string& dest);
// @brief construnct a DML log file name
int getDMLLogFileName(std::string& aDMLLogFileName, const TxnID& txnId) const;
mutable std::map<FileID, CompFileData*> fFileMap;
mutable std::map<IDBDataFile*, CompFileData*> fFilePtrMap;
std::list<std::pair<FileID, ChunkData*> > fActiveChunks;
unsigned int fMaxActiveChunkNum; // max active chunks per file
char* fBufCompressed;
unsigned int fLenCompressed;
unsigned int fMaxCompressedBufSize;
unsigned int fUserPaddings;
bool fIsBulkLoad;
bool fDropFdCache;
bool fIsInsert;
bool fIsHdfs;
FileOp* fFileOp;
compress::IDBCompressInterface fCompressor;
logging::Logger* fSysLogger;
TxnID fTransId;
int fLocalModuleId;
idbdatafile::IDBFileSystem& fFs;
bool fIsFix;
private:
};
}
#undef EXPORT
#endif // CHUNK_MANAGER_H

View File

@ -0,0 +1,681 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_config.cpp 4737 2013-08-14 20:45:46Z bwilkinson $
*
*******************************************************************************/
/** @file */
#include <string>
#include <boost/thread.hpp>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;
#include "configcpp.h"
#include "liboamcpp.h"
#include "installdir.h"
#include "we_config.h"
using namespace config;
#include "IDBPolicy.h"
using namespace idbdatafile;
#include <boost/algorithm/string.hpp>
namespace WriteEngine
{
const int DEFAULT_WAIT_PERIOD = 10;
const unsigned DEFAULT_FILES_PER_COLUMN_PARTITION = 4;
const unsigned DEFAULT_EXTENTS_PER_SEGMENT_FILE = 2;
const int DEFAULT_BULK_PROCESS_PRIORITY = -1;
const unsigned DEFAULT_MAX_FILESYSTEM_DISK_USAGE = 98; // allow 98% full
const unsigned DEFAULT_COMPRESSED_PADDING_BLKS = 1;
const int DEFAULT_LOCAL_MODULE_ID = 1;
const bool DEFAULT_PARENT_OAM = true;
const char* DEFAULT_LOCAL_MODULE_TYPE = "pm";
int Config::m_dbRootCount = 0;
Config::strvec_t Config::m_dbRootPath;
Config::intstrmap_t Config::m_dbRootPathMap;
Config::uint16vec_t Config::m_dbRootId;
string Config::m_bulkRoot;
unsigned long Config::fDBRootChangeCount = 0;
time_t Config::fCacheTime = 0;
boost::mutex Config::fCacheLock;
#ifdef SHARED_NOTHING_DEMO_2
boost::mutex Config::m_bulkRoot_lk;
#endif
int Config::m_WaitPeriod = DEFAULT_WAIT_PERIOD;
unsigned Config::m_FilesPerColumnPartition =
DEFAULT_FILES_PER_COLUMN_PARTITION;
unsigned Config::m_ExtentsPerSegmentFile =
DEFAULT_EXTENTS_PER_SEGMENT_FILE;
int Config::m_BulkProcessPriority = DEFAULT_BULK_PROCESS_PRIORITY;
string Config::m_BulkRollbackDir;
unsigned Config::m_MaxFileSystemDiskUsage =
DEFAULT_MAX_FILESYSTEM_DISK_USAGE;
unsigned Config::m_NumCompressedPadBlks =DEFAULT_COMPRESSED_PADDING_BLKS;
bool Config::m_ParentOAMModuleFlag = DEFAULT_PARENT_OAM;
string Config::m_LocalModuleType;
int Config::m_LocalModuleID = DEFAULT_LOCAL_MODULE_ID;
string Config::m_VersionBufferDir;
/*******************************************************************************
* DESCRIPTION:
* Loads config parms into local cache.
* Call can be made to initConfigCache() at the start
* of the program to initialize local cache, before calling accessors.
* PARAMETERS:
* none
******************************************************************************/
void Config::initConfigCache()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
}
/*******************************************************************************
* DESCRIPTION:
* Reload local cache using contents of Calpont.xml file.
* PARAMETERS:
* none
******************************************************************************/
void Config::checkReload( )
{
bool bFirstLoad = false;
if (fCacheTime == 0)
bFirstLoad = true;
config::Config* cf = config::Config::makeConfig();
// Immediately return if Calpont.xml timestamp has not changed
if (cf->getCurrentMTime() == fCacheTime)
return;
//std::cout << "RELOADING cache..." << std::endl;
//--------------------------------------------------------------------------
// Initialize bulk root directory
//--------------------------------------------------------------------------
m_bulkRoot = cf->getConfig("WriteEngine", "BulkRoot");
if ( m_bulkRoot.length() == 0 )
{
m_bulkRoot = startup::StartUp::installDir();
#ifndef _MSC_VER
m_bulkRoot += "/data";
#endif
m_bulkRoot += "/bulk";
}
// Get latest Calpont.xml timestamp after first access forced a reload
fCacheTime = cf ->getLastMTime();
//--------------------------------------------------------------------------
// Initialize time interval (in seconds) between retries
//--------------------------------------------------------------------------
m_WaitPeriod = DEFAULT_WAIT_PERIOD;
string waitPeriodStr = cf->getConfig("SystemConfig", "WaitPeriod");
if ( waitPeriodStr.length() != 0 )
m_WaitPeriod = static_cast<int>(config::Config::fromText(
waitPeriodStr));
//--------------------------------------------------------------------------
// Initialize files per column partition
//--------------------------------------------------------------------------
m_FilesPerColumnPartition = DEFAULT_FILES_PER_COLUMN_PARTITION;
string fpc = cf->getConfig("ExtentMap", "FilesPerColumnPartition");
if ( fpc.length() != 0 )
m_FilesPerColumnPartition = cf->uFromText(fpc);
//--------------------------------------------------------------------------
// Initialize extents per segment file
//--------------------------------------------------------------------------
m_ExtentsPerSegmentFile = DEFAULT_EXTENTS_PER_SEGMENT_FILE;
string epsf = cf->getConfig("ExtentMap", "ExtentsPerSegmentFile");
if ( epsf.length() != 0 )
m_ExtentsPerSegmentFile = cf->uFromText(epsf);
//--------------------------------------------------------------------------
// Initialize bulk load process priority
//--------------------------------------------------------------------------
m_BulkProcessPriority = DEFAULT_BULK_PROCESS_PRIORITY;
string prior = cf->getConfig("WriteEngine", "Priority");
if ( prior.length() != 0 )
{
int initialBPP = cf->fromText(prior);
// config file priority is 40..1 (highest..lowest)
// convert config file value to setpriority(2) value(-20..19, -1 is the
// default)
if (initialBPP > 0)
m_BulkProcessPriority = 20 - initialBPP;
else if (initialBPP < 0)
m_BulkProcessPriority = 19;
if (m_BulkProcessPriority < -20)
m_BulkProcessPriority = -20;
}
//--------------------------------------------------------------------------
// Initialize bulk rollback directory
// Note this uses m_bulkRoot, so this init section must be after the section
// that sets m_bulkRoot.
//--------------------------------------------------------------------------
m_BulkRollbackDir = cf->getConfig("WriteEngine", "BulkRollbackDir");
if (m_BulkRollbackDir.length() == 0)
{
m_BulkRollbackDir.assign( m_bulkRoot );
m_BulkRollbackDir += "/rollback";
}
//--------------------------------------------------------------------------
// Initialize max disk usage
//--------------------------------------------------------------------------
m_MaxFileSystemDiskUsage = DEFAULT_MAX_FILESYSTEM_DISK_USAGE;
string usg = cf->getConfig("WriteEngine", "MaxFileSystemDiskUsagePct");
if ( usg.length() != 0 )
m_MaxFileSystemDiskUsage = cf->uFromText(usg);
if (m_MaxFileSystemDiskUsage > 100)
m_MaxFileSystemDiskUsage = DEFAULT_MAX_FILESYSTEM_DISK_USAGE;
//--------------------------------------------------------------------------
// Number of compressed padding blocks
//--------------------------------------------------------------------------
m_NumCompressedPadBlks = DEFAULT_COMPRESSED_PADDING_BLKS;
string ncpb = cf->getConfig("WriteEngine", "CompressedPaddingBlocks");
if ( ncpb.length() != 0 )
m_NumCompressedPadBlks = cf->uFromText(ncpb);
#if 0 // common code, moved to IDBPolicy
//--------------------------------------------------------------------------
// IDBDataFile logging
//--------------------------------------------------------------------------
bool idblog = false;
string idblogstr = cf->getConfig("SystemConfig", "DataFileLog");
if ( idblogstr.length() != 0 )
{
boost::to_upper(idblogstr);
idblog = ( idblogstr == "ON" );
}
//--------------------------------------------------------------------------
// Optional File System Plugin - if a HDFS type plugin is loaded
// then the system will use HDFS for all IDB data files
//--------------------------------------------------------------------------
string fsplugin = cf->getConfig("SystemConfig", "DataFilePlugin");
if ( fsplugin.length() != 0 )
{
IDBPolicy::installPlugin(fsplugin);
}
//--------------------------------------------------------------------------
// HDFS file buffering
//--------------------------------------------------------------------------
// Maximum amount of memory to use for hdfs buffering.
bool bUseRdwrMemBuffer = true; // If true, use in-memory buffering, else use file buffering
int64_t hdfsRdwrBufferMaxSize = 0;
string strBufferMaxSize = cf->getConfig("SystemConfig", "hdfsRdwrBufferMaxSize");
if (strBufferMaxSize.length() == 0)
{
// Default is use membuf with no maximum size.
bUseRdwrMemBuffer = true;
}
else
{
hdfsRdwrBufferMaxSize = static_cast<int64_t>(cf->uFromText(strBufferMaxSize));
if ( hdfsRdwrBufferMaxSize == 0 )
{
// If we're given a size of 0, turn off membuffering.
bUseRdwrMemBuffer = false;
}
}
// Directory in which to place file buffer temporary files.
string hdfsRdwrScratch = cf->getConfig("SystemConfig", "hdfsRdwrScratch");
if ( hdfsRdwrScratch.length() == 0 )
{
hdfsRdwrScratch = "/tmp/hdfsscratch";
}
IDBPolicy::init( idblog, bUseRdwrMemBuffer, hdfsRdwrScratch, hdfsRdwrBufferMaxSize );
#endif
IDBPolicy::configIDBPolicy();
//--------------------------------------------------------------------------
// Initialize Parent OAM Module flag
// Initialize Module Type
// Initialize Local Module ID
//--------------------------------------------------------------------------
oam::Oam oam;
oam::oamModuleInfo_t t;
try {
t = oam.getModuleInfo();
m_ParentOAMModuleFlag = boost::get<4>(t);
m_LocalModuleType = boost::get<1>(t);
m_LocalModuleID = boost::get<2>(t);
}
catch (exception&) {
m_ParentOAMModuleFlag = DEFAULT_PARENT_OAM;
m_LocalModuleType.assign( DEFAULT_LOCAL_MODULE_TYPE );
m_LocalModuleID = DEFAULT_LOCAL_MODULE_ID;
}
//--------------------------------------------------------------------------
// Initialize Version Buffer
//--------------------------------------------------------------------------
m_VersionBufferDir = cf->getConfig("SystemConfig", "DBRMRoot");
if ( m_VersionBufferDir.length() == 0 )
{
#ifdef _MSC_VER
m_VersionBufferDir = startup::StartUp::installDir() + "\\version";
#else
m_VersionBufferDir =
startup::StartUp::installDir() + "/data1/systemFiles/dbrm/BRM_saves";
#endif
}
//--------------------------------------------------------------------------
// Initialize m_dbRootCount, m_dbRootPath, m_dbRootPathMap, m_dbRootId.
// Note this uses m_localModuleType and m_LocalModuleID, so this init
// section must be after the section(s) that set m_localModuleType and
// m_LocalModuleID.
//--------------------------------------------------------------------------
uint16vec_t dbRootIdPrevious( m_dbRootId ); // save current settings
strvec_t dbRootPathPrevious( m_dbRootPath ); // save current setttings
m_dbRootPath.clear();
m_dbRootPathMap.clear();
m_dbRootId.clear();
if (m_LocalModuleType == "pm")
{
oam::DBRootConfigList oamRootList;
try {
oam.getPmDbrootConfig( m_LocalModuleID, oamRootList );
std::sort( oamRootList.begin(), oamRootList.end() );
m_dbRootCount = oamRootList.size();
for (unsigned int idx=0; idx<oamRootList.size(); idx++)
{
ostringstream oss;
oss << "DBRoot" << oamRootList[idx];
std::string DbRootPath =
cf->getConfig("SystemConfig", oss.str());
m_dbRootPath.push_back( DbRootPath );
m_dbRootPathMap[ oamRootList[idx] ] = DbRootPath;
m_dbRootId.push_back( oamRootList[idx] );
}
}
catch (exception&) {
m_dbRootCount = 0;
}
}
else
{
m_dbRootCount = 0;
}
// Update counter used to track changes to local PM DBRoot list
if (!bFirstLoad)
{
if ((dbRootIdPrevious != m_dbRootId) ||
(dbRootPathPrevious != m_dbRootPath))
{
fDBRootChangeCount++;
}
}
// for (unsigned int n=0; n<m_dbRootPath.size(); n++)
// {
// std::cout << "dbrootpath: " << n << ". " << m_dbRootPath[n] <<std::endl;
// }
// for (unsigned int n=0; n<m_dbRootId.size(); n++)
// {
// std::cout << "dbrootId: " << n << ". " << m_dbRootId[n] << std::endl;
// }
// for (Config::intstrmap_t::iterator k=m_dbRootPathMap.begin();
// k!=m_dbRootPathMap.end(); ++k)
// {
// std::cout << "dbrootmap: " << k->first << "," << k->second << std::endl;
// }
}
/*******************************************************************************
* DESCRIPTION:
* Get db root count for local PM
* PARAMETERS:
* none
* RETURN:
* Number of DBRoot paths to be used for database files
******************************************************************************/
size_t Config::DBRootCount()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_dbRootCount;
}
/*******************************************************************************
* DESCRIPTION:
* Get db root
* PARAMETERS:
* idx - Index of the DBRootn entry to fetch (0 fetches DBRoot[0],etc.)
* RETURN:
* DBRoot path for specified index
******************************************************************************/
std::string Config::getDBRootByIdx(unsigned idx)
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
if (idx >= m_dbRootPath.size())
{
std::string emptyResult;
return emptyResult;
}
return m_dbRootPath[idx];
}
/*******************************************************************************
* DESCRIPTION:
* Get db root path list for the local PM
* PARAMETERS:
* dbRootPathList - return list of DBRoot paths
* RETURN:
* none
******************************************************************************/
void Config::getDBRootPathList( std::vector<std::string>& dbRootPathList )
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
dbRootPathList.clear();
dbRootPathList = m_dbRootPath;
}
/*******************************************************************************
* DESCRIPTION:
* Get db root
* PARAMETERS:
* num - DBRootN entry to fetch (1 fetches DBRoot1, etc.)
* RETURN:
* DBRoot path for specified index
******************************************************************************/
std::string Config::getDBRootByNum(unsigned num)
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
Config::intstrmap_t::const_iterator iter = m_dbRootPathMap.find( num );
if (iter == m_dbRootPathMap.end())
{
std::string emptyResult;
return emptyResult;
}
return iter->second;
}
/*******************************************************************************
* DESCRIPTION:
* Get list of applicable DBRoot ids for this job.
* PARAMETERS:
* N/A
* RETURN:
* The list of DBRoot ids
******************************************************************************/
void Config::getRootIdList( std::vector<uint16_t>& rootIds )
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
rootIds = m_dbRootId;
}
/*******************************************************************************
* DESCRIPTION:
* Get bulk root
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, other otherwise
******************************************************************************/
std::string Config::getBulkRoot()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_bulkRoot;
}
#ifdef SHARED_NOTHING_DEMO_2
void Config::getSharedNothingRoot(char *ret)
{
string root;
boost::mutex::scoped_lock lk(m_bulkRoot_lk);
root = config::Config::makeConfig()->getConfig(
"WriteEngine", "SharedNothingRoot");
strncpy(ret, root.c_str(), FILE_NAME_SIZE);
}
#endif
/*******************************************************************************
* DESCRIPTION:
* Get wait period used between tries to get a transaction id.
* PARAMETERS:
* none
* RETURN:
* Wait Period in seconds
******************************************************************************/
int Config::getWaitPeriod()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_WaitPeriod;
}
/*******************************************************************************
* DESCRIPTION:
* Get number of segment files per column partition.
* PARAMETERS:
* none
* RETURN:
* Number of files
******************************************************************************/
unsigned Config::getFilesPerColumnPartition()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_FilesPerColumnPartition;
}
/*******************************************************************************
* DESCRIPTION:
* Get number of extents per column segment file
* PARAMETERS:
* none
* RETURN:
* Number of extents
******************************************************************************/
unsigned Config::getExtentsPerSegmentFile()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_ExtentsPerSegmentFile;
}
/*******************************************************************************
* DESCRIPTION:
* Get process priority for cpimport.bin process.
* Config file priority is in range 40..1 (highest..lowest)
* Return value is in range (-20..19)
*
* This range of values 40..1, and -20..19, matches the
* convention used by PrimProc and ExeMgr, so that we are
* consistent with those processes. Likewise we employ
* the same default priority of -1.
* PARAMETERS:
* none
* RETURN:
* cpimport.bin process priority
******************************************************************************/
int Config::getBulkProcessPriority()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_BulkProcessPriority;
}
/*******************************************************************************
* DESCRIPTION:
* Get bulk rollback directory path.
* PARAMETERS:
* none
******************************************************************************/
std::string Config::getBulkRollbackDir()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_BulkRollbackDir;
}
/*******************************************************************************
* DESCRIPTION:
* Get Max percentage of allowable file system disk usage for each DBRoot
* PARAMETERS:
* none
******************************************************************************/
unsigned Config::getMaxFileSystemDiskUsage()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_MaxFileSystemDiskUsage;
}
/*******************************************************************************
* DESCRIPTION:
* Get number of blocks to use in padding each compressed chunk (only
* applies to compressed columns).
* PARAMETERS:
* none
******************************************************************************/
unsigned Config::getNumCompressedPadBlks()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_NumCompressedPadBlks;
}
/*******************************************************************************
* DESCRIPTION:
* Get Parent OAM Module flag; are we running on active parent OAM node.
* PARAMETERS:
* none
******************************************************************************/
bool Config::getParentOAMModuleFlag()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_ParentOAMModuleFlag;
}
/*******************************************************************************
* DESCRIPTION:
* Get Module type (ex: "pm")
* PARAMETERS:
* none
******************************************************************************/
std::string Config::getLocalModuleType()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_LocalModuleType;
}
/*******************************************************************************
* DESCRIPTION:
* Get Module ID number (ex: 1)
* PARAMETERS:
* none
******************************************************************************/
uint16_t Config::getLocalModuleID()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_LocalModuleID;
}
/*******************************************************************************
* DESCRIPTION:
* Get version buffer root
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, other otherwise
******************************************************************************/
std::string Config::getVBRoot()
{
boost::mutex::scoped_lock lk(fCacheLock);
checkReload( );
return m_VersionBufferDir;
}
/*******************************************************************************
* DESCRIPTION:
* Has the DBRoot list for the local PM changed since the last time this
* function was called.
* PARAMETERS:
* none
* RETURN:
* returns TRUE if local DBRoot list has changed since the last call.
******************************************************************************/
bool Config::hasLocalDBRootListChanged()
{
boost::mutex::scoped_lock lk(fCacheLock);
if (fDBRootChangeCount > 0)
{
fDBRootChangeCount = 0;
return true;
}
return false;
}
} //end of namespace

View File

@ -0,0 +1,201 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_config.h 4726 2013-08-07 03:38:36Z bwilkinson $
*
*******************************************************************************/
/** @file */
#ifndef WE_CONFIG_H_
#define WE_CONFIG_H_
#include <string>
#include <boost/thread.hpp>
#include <vector>
#include <map>
#include "we_obj.h"
//#define SHARED_NOTHING_DEMO_2
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
/** Class Config */
class Config
{
public:
/**
* @brief Constructor
*/
Config() {}
/**
* @brief Default Destructor
*/
~Config() {}
/**
* @brief Get DB root (for local PM)
* @param idx Index of the DBRootn entry to fetch (0 fetches DBRoot[0],etc.)
*/
EXPORT static std::string getDBRootByIdx(unsigned idx);
/**
* @brief Get complete DBRoot path list for the local PM
* @param dbRootPathList vector of DBRoot paths
*/
EXPORT static void getDBRootPathList(
std::vector<std::string>& dbRootPathList );
/**
* @brief Get DB root (for local PM)
* @param num DBRootN entry to fetch (1 fetches DBRoot1, etc.)
*/
EXPORT static std::string getDBRootByNum(unsigned num);
/**
* @brief Get list of applicable DBRoot ids for this job.
*/
EXPORT static void getRootIdList( std::vector<uint16_t>& dbRootIds );
#ifdef SHARED_NOTHING_DEMO_2
EXPORT static void getSharedNothingRoot(char *); // pass in an char[FILE_NAME_SIZE]
#endif
/**
* @brief Bulkload DB root
*/
EXPORT static std::string getBulkRoot();
/**
* @brief DBRoot count for local PM
*/
EXPORT static size_t DBRootCount();
/**
* @brief Wait Period
*/
EXPORT static int getWaitPeriod();
/**
* @brief FilesPerColumnPartition
*/
EXPORT static unsigned getFilesPerColumnPartition();
/**
* @brief ExtentsPerSegmentFile
*/
EXPORT static unsigned getExtentsPerSegmentFile();
/**
* @brief Process Priority for cpimport.bin
* Return value is in range -20..19 (highest...lowest, 0=normal)
*/
EXPORT static int getBulkProcessPriority();
/**
* @brief Directory carrying Bulk Rollback meta data files
*/
EXPORT static std::string getBulkRollbackDir();
/**
* @brief Max percentage of allowable file system disk usage for each DBRoot
*/
EXPORT static unsigned getMaxFileSystemDiskUsage();
/**
* @brief Number of Blocks to pad each compressed chunk.
*/
EXPORT static unsigned getNumCompressedPadBlks();
/**
* @brief Parent OAM Module flag (is this the parent OAM node, ex: pm1)
*/
EXPORT static bool getParentOAMModuleFlag();
/**
* @brief Local Module Type (ex: "pm")
*/
EXPORT static std::string getLocalModuleType();
/**
* @brief Local Module ID (ex: 1 )
*/
EXPORT static uint16_t getLocalModuleID();
/**
* @brief Version Buffer root
*/
EXPORT static std::string getVBRoot();
/**
* @brief Cache the config parameters locally
* Initialize Config cache. Cache will be updated as needed.
*/
EXPORT static void initConfigCache();
/**
* @brief Has Local PM DBRoot info changed since last time this function
* was called. Can be used to monitor changes to DBRoot info.
*/
EXPORT static bool hasLocalDBRootListChanged();
private:
typedef std::vector<std::string> strvec_t;
typedef std::map<int,std::string> intstrmap_t;
typedef std::vector<uint16_t> uint16vec_t;
static void checkReload();
static int m_dbRootCount; // num DBRoots for local PM
static strvec_t m_dbRootPath; // root paths for open files
static intstrmap_t m_dbRootPathMap; // map of root id to root paths
static uint16vec_t m_dbRootId; // list of root ids
static std::string m_bulkRoot; // root path for bulk operation
static unsigned long fDBRootChangeCount; // track recent DBRoot changes
static time_t fCacheTime; // timestamp associated w/cache
static boost::mutex fCacheLock; // mutex for m_dbRoot sync
#ifdef SHARED_NOTHING_DEMO_2
static boost::mutex m_bulkRoot_lk; // mutex for m_bulkRoot sync
#endif
static int m_WaitPeriod; // secs to wait for transaction
static unsigned m_FilesPerColumnPartition;//# seg files per partition
static unsigned m_ExtentsPerSegmentFile; // # extents per segment file
static int m_BulkProcessPriority; // cpimport.bin proc priority
static std::string m_BulkRollbackDir; // bulk rollback meta data dir
static unsigned m_MaxFileSystemDiskUsage;// max file system % disk usage
static unsigned m_NumCompressedPadBlks; // num blks to pad comp chunks
static bool m_ParentOAMModuleFlag; // are we running on parent PM
static std::string m_LocalModuleType; // local node type (ex: "pm")
static int m_LocalModuleID; // local node id (ex: 1 )
static std::string m_VersionBufferDir; // Version buffer directory
};
} //end of namespace
#undef EXPORT
#endif // WE_CONFIG_H_

View File

@ -0,0 +1,823 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
#include "we_confirmhdfsdbfile.h"
#include <cerrno>
#include <cstring>
#include <iostream>
#include <sstream>
#include <vector>
#include <boost/scoped_array.hpp>
#include <boost/scoped_ptr.hpp>
#include "we_define.h"
#include "we_config.h"
#include "we_fileop.h"
#include "we_rbmetawriter.h"
#include "IDBPolicy.h"
#include "IDBDataFile.h"
namespace
{
const int BUF_SIZE = 1024; // size of buffer used to read meta data records
}
namespace WriteEngine
{
//------------------------------------------------------------------------------
// Constructor
// This class should typically only be used on an HDFS system, so we could
// hardcode this to pass HDFS to getFsi(); but it comes in handy for testing,
// to be able to execute this class on a non-HDFS stack as well. So I rely
// on useHdfs() to tell me which FileSystem reference to get.
//------------------------------------------------------------------------------
ConfirmHdfsDbFile::ConfirmHdfsDbFile() :
fFs( (idbdatafile::IDBPolicy::useHdfs()) ?
idbdatafile::IDBFileSystem::getFs(idbdatafile::IDBDataFile::HDFS) :
idbdatafile::IDBFileSystem::getFs(idbdatafile::IDBDataFile::BUFFERED))
{
}
//------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------
ConfirmHdfsDbFile::~ConfirmHdfsDbFile()
{
}
//------------------------------------------------------------------------------
// Backup a cdf file and replace it with the updated tmp file.
//------------------------------------------------------------------------------
int ConfirmHdfsDbFile::confirmDbFileChange(
const std::string& backUpFileType,
const std::string& filename,
std::string& errMsg) const
{
// return value
int rc = NO_ERROR;
// This rlc file should be renamed if success, just skip it
if (backUpFileType.compare("rlc") == 0)
{
return rc;
}
if (backUpFileType.compare("tmp") != 0 )
{
std::ostringstream oss;
oss << backUpFileType << " is a bad type to confirm DbFile change: " <<
filename;
errMsg = oss.str();
rc = ERR_HDFS_BACKUP;
return rc;
}
// add safety checks, just in case
std::string tmp(filename + ".tmp");
if (!fFs.exists(tmp.c_str())) // file already swapped
return rc;
if (fFs.size(tmp.c_str()) <= 0)
{
std::ostringstream oss;
oss << "tmp file " << tmp << " has bad size" << fFs.size(tmp.c_str());
errMsg = oss.str();
rc = ERR_COMP_RENAME_FILE;
return rc;
}
// remove the old orig if exists
std::string orig(filename + ".orig");
errno = 0;
if ((fFs.exists(orig.c_str())) &&
(fFs.remove(orig.c_str())) != 0)
{
int errNum = errno;
std::ostringstream oss;
oss << "remove old " << orig << " failed: " << strerror(errNum);
errMsg = oss.str();
rc = ERR_COMP_REMOVE_FILE;
return rc;
}
// backup the original
errno = 0;
if (fFs.rename(filename.c_str(), orig.c_str()) != 0)
{
int errNum = errno;
std::ostringstream oss;
oss << "rename " << filename << " to " << orig << " failed: " <<
strerror(errNum);
errMsg = oss.str();
rc = ERR_COMP_RENAME_FILE;
return rc;
}
// rename the new file
errno = 0;
if (fFs.rename(tmp.c_str(), filename.c_str()) != 0)
{
int errNum = errno;
std::ostringstream oss;
oss << "rename " << tmp << " to " << filename << " failed: " <<
strerror(errNum);
errMsg = oss.str();
rc = ERR_COMP_RENAME_FILE;
return rc;
}
return rc;
}
//------------------------------------------------------------------------------
// Finalize the changes to a db file.
// If success flag is true, then remove the orig
// otherwise, move the orig back to cdf
//------------------------------------------------------------------------------
int ConfirmHdfsDbFile::endDbFileChange(
const std::string& backUpFileType,
const std::string& filename,
bool success,
std::string& errMsg) const
{
// return value
int rc = NO_ERROR;
// This rlc file should be renamed if success, it is useless if failed.
if (backUpFileType.compare("rlc") == 0)
{
std::string rlc(filename + ".rlc");
if (fFs.exists(rlc.c_str()))
fFs.remove(rlc.c_str()); // TBD-okay to ignore failed removal?
return rc;
}
if (backUpFileType.compare("tmp") != 0)
{
std::ostringstream oss;
oss << backUpFileType << " is a bad type to finalize DbFile change: " <<
filename;
errMsg = oss.str();
rc = ERR_HDFS_BACKUP;
return rc;
}
std::string orig(filename + ".orig");
if (success)
{
// remove the orig file
errno = 0;
if ((fFs.exists(orig.c_str())) &&
(fFs.remove(orig.c_str())) != 0)
{
int errNum = errno;
std::ostringstream oss;
oss << "remove " << orig << " failed: " << strerror(errNum);
errMsg = oss.str();
rc = ERR_COMP_REMOVE_FILE;
return rc;
}
}
else
{
// restore the orig file
if (fFs.exists(orig.c_str()))
{
errno = 0;
// Try to remove file only if it exists
if ((fFs.exists(filename.c_str())) &&
(fFs.remove(filename.c_str()) != 0))
{
int errNum = errno;
std::ostringstream oss;
oss << "failed restore; remove " << filename << " failed: " <<
strerror(errNum);
errMsg = oss.str();
rc = ERR_COMP_REMOVE_FILE;
return rc;
}
errno = 0;
if (fFs.rename(orig.c_str(), filename.c_str()) != 0)
{
int errNum = errno;
std::ostringstream oss;
oss << "failed restore; rename " << orig << " failed: " <<
strerror(errNum);
errMsg = oss.str();
rc = ERR_COMP_RENAME_FILE;
return rc;
}
}
// remove the tmp file
std::string tmp(filename + ".tmp");
errno = 0;
if ((fFs.exists(tmp.c_str())) &&
(fFs.remove(tmp.c_str())) != 0)
{
int errNum = errno;
std::ostringstream oss;
oss << "failed restore; remove " << tmp << " failed: " <<
strerror(errNum);
errMsg = oss.str();
rc = ERR_COMP_REMOVE_FILE;
return rc;
}
// remove the chunk shifting helper
std::string rlc(filename + ".rlc");
errno = 0;
if ((fFs.exists(rlc.c_str())) &&
(fFs.remove(rlc.c_str())) != 0)
{
int errNum = errno;
std::ostringstream oss;
oss << "failed restore; remove " << rlc << " failed: " <<
strerror(errNum);
errMsg = oss.str();
rc = ERR_COMP_REMOVE_FILE;
return rc;
}
}
return rc;
}
//------------------------------------------------------------------------------
// Confirm the changes to the hwm DB files listed in the bulk rollback meta
// data file corresponding to the specified table OID.
//------------------------------------------------------------------------------
int ConfirmHdfsDbFile::confirmDbFileListFromMetaFile(
OID tableOID,
std::string& errMsg)
{
int rc = NO_ERROR;
try
{
std::vector<uint16_t> dbRoots;
Config::getRootIdList( dbRoots );
for (unsigned m=0; m<dbRoots.size(); m++)
{
std::istringstream metaDataStream;
openMetaDataFile ( tableOID,
dbRoots[m], metaDataStream );
confirmDbFiles( metaDataStream );
}
}
catch (WeException& ex)
{
std::ostringstream oss;
oss << "Error confirming changes to table " << tableOID <<
"; " << ex.what();
errMsg = oss.str();
rc = ex.errorCode();
}
catch (std::exception& ex)
{
std::ostringstream oss;
oss << "Error confirming changes to table " << tableOID <<
"; " << ex.what();
errMsg = oss.str();
rc = ERR_UNKNOWN;
}
return rc;
}
//------------------------------------------------------------------------------
// Confirm the changes to the hwm DB files listed in the bulk rollback meta
// data file stream stored in metaDataStream.
//------------------------------------------------------------------------------
void ConfirmHdfsDbFile::confirmDbFiles(std::istringstream& metaDataStream) const
{
char inBuf[ BUF_SIZE ];
// Loop through the records in the meta-data file
while (metaDataStream.getline( inBuf, BUF_SIZE ))
{
// Restore Files for current DBRoot
if (RBMetaWriter::verifyColumn1Rec(inBuf))
{
confirmColumnDbFile(inBuf);
}
else if (RBMetaWriter::verifyDStore1Rec(inBuf))
{
confirmDctnryStoreDbFile(inBuf);
}
}
}
//------------------------------------------------------------------------------
// Confirm the changes to the hwm column DB file described in the bulk
// rollback meta data file record stored in inBuf.
//------------------------------------------------------------------------------
void ConfirmHdfsDbFile::confirmColumnDbFile(const char* inBuf) const
{
char recType[100];
OID columnOID;
uint32_t dbRootHwm;
uint32_t partNumHwm;
uint32_t segNumHwm;
HWM lastLocalHwm;
int colTypeInt;
char colTypeName[100];
uint32_t colWidth;
int compressionType = 0; // optional parameter
// Read meta-data record
int numFields = sscanf(inBuf, "%s %u %u %u %u %u %d %s %u %d",
recType, &columnOID,
&dbRootHwm, &partNumHwm, &segNumHwm, &lastLocalHwm,
&colTypeInt, colTypeName, &colWidth, &compressionType );
if (numFields < 9) // compressionType is optional
{
std::ostringstream oss;
oss << "Invalid COLUM1 record in meta-data file " <<
fMetaFileName << "; record-<" << inBuf << ">";
throw WeException( oss.str(), ERR_INVALID_PARAM );
}
// Construct the DB file name
char dbFileName[FILE_NAME_SIZE];
FileOp dbFile(false);
int rc = dbFile.getFileName( columnOID,
dbFileName,
dbRootHwm,
partNumHwm,
segNumHwm );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error constructing column filename to confirm changes" <<
"; columnOID-" << columnOID <<
"; dbRoot-" << dbRootHwm <<
"; partNum-" << partNumHwm <<
"; segNum-" << segNumHwm <<
"; " << ec.errorString(rc);
throw WeException( oss.str(), rc );
}
// Confirm the changes to the DB file name
std::string errMsg;
rc = confirmDbFileChange( std::string("tmp"),
dbFileName,
errMsg );
if (rc != NO_ERROR)
{
throw WeException( errMsg, rc );
}
}
//------------------------------------------------------------------------------
// Confirm the changes to the hwm dctnry store DB file described in the bulk
// rollback meta data file record stored in inBuf.
//------------------------------------------------------------------------------
void ConfirmHdfsDbFile::confirmDctnryStoreDbFile(const char* inBuf) const
{
char recType[100];
OID dColumnOID;
OID dStoreOID;
uint32_t dbRootHwm;
uint32_t partNumHwm;
uint32_t segNumHwm;
HWM localHwm;
int compressionType = 0; // optional parameter
// Read meta-data record
int numFields = sscanf(inBuf, "%s %u %u %u %u %u %u %d",
recType, &dColumnOID, &dStoreOID,
&dbRootHwm, &partNumHwm, &segNumHwm, &localHwm, &compressionType );
if (numFields < 7) // compressionType optional
{
std::ostringstream oss;
oss << "Invalid DSTOR1 record in meta-data file " <<
fMetaFileName << "; record-<" << inBuf << ">";
throw WeException( oss.str(), ERR_INVALID_PARAM );
}
// Construct the DB file name
char dbFileName[FILE_NAME_SIZE];
FileOp dbFile(false);
int rc = dbFile.getFileName( dStoreOID,
dbFileName,
dbRootHwm,
partNumHwm,
segNumHwm );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss<<"Error constructing dictionary store filename to confirm changes"<<
"; columnOID-" << dStoreOID <<
"; dbRoot-" << dbRootHwm <<
"; partNum-" << partNumHwm <<
"; segNum-" << segNumHwm <<
"; " << ec.errorString(rc);
throw WeException( oss.str(), rc );
}
// Confirm the changes to the DB file name
std::string errMsg;
rc = confirmDbFileChange( std::string("tmp"),
dbFileName,
errMsg );
if (rc != NO_ERROR)
{
throw WeException( errMsg, rc );
}
}
//------------------------------------------------------------------------------
// End the changes to the hwm DB files listed in the bulk rollback meta
// data file corresponding to the specified table OID. Delete temp files.
//------------------------------------------------------------------------------
int ConfirmHdfsDbFile::endDbFileListFromMetaFile(
OID tableOID,
bool success,
std::string& errMsg)
{
int rc = NO_ERROR;
errMsg.clear();
std::vector<uint16_t> dbRoots;
Config::getRootIdList( dbRoots );
for (unsigned m=0; m<dbRoots.size(); m++)
{
std::istringstream metaDataStream;
try
{
std::istringstream metaDataStream;
openMetaDataFile ( tableOID,
dbRoots[m], metaDataStream );
endDbFiles( metaDataStream, success );
}
// We catch any errors, but not deleting a temp file is not fatal,
// so we capture the error msg and keep going if a problem occurs.
// We return a concatenated list of error msgs if multiple errors
// take place.
catch (WeException& ex)
{
if (errMsg.size() == 0)
{
std::ostringstream oss;
oss << "Error deleting temp files for table " << tableOID <<
"; " << ex.what();
errMsg = oss.str();
rc = ex.errorCode();
}
else
{
errMsg += "; ";
errMsg += ex.what();
}
}
catch (std::exception& ex)
{
if (errMsg.size() == 0)
{
std::ostringstream oss;
oss << "Error deleting temp files for table " << tableOID <<
"; " << ex.what();
errMsg = oss.str();
rc = ERR_UNKNOWN;
}
else
{
errMsg += "; ";
errMsg += ex.what();
}
}
}
return rc;
}
//------------------------------------------------------------------------------
// End the changes to the hwm DB files listed in the bulk rollback meta
// data file stream stored in metaDataStream. Delete temp files.
//------------------------------------------------------------------------------
void ConfirmHdfsDbFile::endDbFiles(
std::istringstream& metaDataStream,
bool success) const
{
char inBuf[ BUF_SIZE ];
std::string errMsg;
int rc = NO_ERROR;
// Loop through the records in the meta-data file
while (metaDataStream.getline( inBuf, BUF_SIZE ))
{
try
{
// Delete Temp Files for current DBRoot
if (RBMetaWriter::verifyColumn1Rec(inBuf))
{
endColumnDbFile(inBuf, success);
}
else if (RBMetaWriter::verifyDStore1Rec(inBuf))
{
endDctnryStoreDbFile(inBuf, success);
}
}
// We catch any errors, but not deleting a temp file is not fatal,
// so we capture the error msg and keep going if a problem occurs.
// We return a concatenated list of error msgs if multiple errors
// take place.
catch (WeException& ex)
{
if (errMsg.size() == 0)
{
rc = ex.errorCode();
}
else
{
errMsg += "; ";
}
errMsg += ex.what();
}
catch (std::exception& ex)
{
if (errMsg.size() == 0)
{
rc = ERR_UNKNOWN;
}
else
{
errMsg += "; ";
}
errMsg += ex.what();
}
}
// Throw exception with cumulative list of any error msgs
if (errMsg.size() > 0)
{
throw WeException( errMsg, rc );
}
}
//------------------------------------------------------------------------------
// End the changes to the hwm column DB file described in the bulk
// rollback meta data file record stored in inBuf. Delete the temp file.
//------------------------------------------------------------------------------
void ConfirmHdfsDbFile::endColumnDbFile(
const char* inBuf,
bool success) const
{
char recType[100];
OID columnOID;
uint32_t dbRootHwm;
uint32_t partNumHwm;
uint32_t segNumHwm;
HWM lastLocalHwm;
int colTypeInt;
char colTypeName[100];
uint32_t colWidth;
int compressionType = 0; // optional parameter
// Read meta-data record
int numFields = sscanf(inBuf, "%s %u %u %u %u %u %d %s %u %d",
recType, &columnOID,
&dbRootHwm, &partNumHwm, &segNumHwm, &lastLocalHwm,
&colTypeInt, colTypeName, &colWidth, &compressionType );
if (numFields < 9) // compressionType is optional
{
std::ostringstream oss;
oss << "Invalid COLUM1 record in meta-data file " <<
fMetaFileName << "; record-<" << inBuf << ">";
throw WeException( oss.str(), ERR_INVALID_PARAM );
}
// Construct the DB file name
char dbFileName[FILE_NAME_SIZE];
FileOp dbFile(false);
int rc = dbFile.getFileName( columnOID,
dbFileName,
dbRootHwm,
partNumHwm,
segNumHwm );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss << "Error constructing column filename to end changes" <<
"; columnOID-" << columnOID <<
"; dbRoot-" << dbRootHwm <<
"; partNum-" << partNumHwm <<
"; segNum-" << segNumHwm <<
"; " << ec.errorString(rc);
throw WeException( oss.str(), rc );
}
// Confirm the changes to the DB file name
std::string errMsg;
rc = endDbFileChange( std::string("tmp"),
dbFileName,
success,
errMsg );
if (rc != NO_ERROR)
{
throw WeException( errMsg, rc );
}
}
//------------------------------------------------------------------------------
// End the changes to the hwm dctnry store DB file described in the bulk
// rollback meta data file record stored in inBuf. Delete the temp file.
//------------------------------------------------------------------------------
void ConfirmHdfsDbFile::endDctnryStoreDbFile(
const char* inBuf,
bool success) const
{
char recType[100];
OID dColumnOID;
OID dStoreOID;
uint32_t dbRootHwm;
uint32_t partNumHwm;
uint32_t segNumHwm;
HWM localHwm;
int compressionType = 0; // optional parameter
// Read meta-data record
int numFields = sscanf(inBuf, "%s %u %u %u %u %u %u %d",
recType, &dColumnOID, &dStoreOID,
&dbRootHwm, &partNumHwm, &segNumHwm, &localHwm, &compressionType );
if (numFields < 7) // compressionType optional
{
std::ostringstream oss;
oss << "Invalid DSTOR1 record in meta-data file " <<
fMetaFileName << "; record-<" << inBuf << ">";
throw WeException( oss.str(), ERR_INVALID_PARAM );
}
// Construct the DB file name
char dbFileName[FILE_NAME_SIZE];
FileOp dbFile(false);
int rc = dbFile.getFileName( dStoreOID,
dbFileName,
dbRootHwm,
partNumHwm,
segNumHwm );
if (rc != NO_ERROR)
{
WErrorCodes ec;
std::ostringstream oss;
oss<<"Error constructing dictionary store filename to end changes"<<
"; columnOID-" << dStoreOID <<
"; dbRoot-" << dbRootHwm <<
"; partNum-" << partNumHwm <<
"; segNum-" << segNumHwm <<
"; " << ec.errorString(rc);
throw WeException( oss.str(), rc );
}
// Confirm the changes to the DB file name
std::string errMsg;
rc = endDbFileChange( std::string("tmp"),
dbFileName,
success,
errMsg );
if (rc != NO_ERROR)
{
throw WeException( errMsg, rc );
}
}
//------------------------------------------------------------------------------
// Open and read the bulk rollback metadata file for the specified table OID
// and DBRoot. The contents of the metadata file is returned in the meta-
// DataStream argument.
//------------------------------------------------------------------------------
void ConfirmHdfsDbFile::openMetaDataFile(OID tableOID,
uint16_t dbRoot,
std::istringstream& metaDataStream)
{
std::string bulkRollbackPath( Config::getDBRootByNum( dbRoot ) );
// Construct file name and check for it's existence
std::ostringstream ossFileName;
ossFileName << '/' << DBROOT_BULK_ROLLBACK_SUBDIR << '/' << tableOID;
fMetaFileName = bulkRollbackPath;
fMetaFileName += ossFileName.str();
// Return if the meta-data file does not exist.
if ( !fFs.exists( fMetaFileName.c_str() ) )
{
std::ostringstream oss;
oss << "Bulk rollback meta-data file " <<
fMetaFileName << " does not exist.";
throw WeException( oss.str(), ERR_FILE_NOT_EXIST );
}
// Open the file
boost::scoped_ptr<IDBDataFile> metaFile;
errno = 0;
metaFile.reset(idbdatafile::IDBDataFile::open(
idbdatafile::IDBPolicy::getType(fMetaFileName.c_str(),
idbdatafile::IDBPolicy::WRITEENG),
fMetaFileName.c_str(), "rb", 0) );
if ( !metaFile )
{
int errRc = errno;
std::ostringstream oss;
oss << "Error opening bulk rollback meta-data file " <<
fMetaFileName << "; err-" <<
errRc << "; " << strerror( errRc );
throw WeException( oss.str(), ERR_FILE_OPEN );
}
// First record in the file must be a Version record.
char inBuf[ BUF_SIZE ];
ssize_t metaFileSize = fFs.size( fMetaFileName.c_str() );
boost::scoped_array<char> buf( new char[ metaFileSize ] );
// retry 10 times for partial reads, just in case
ssize_t readSofar = 0; // bytes read so far
ssize_t bytes = 0; // bytes read by one pread
char* p = buf.get();
for (int i = 0; i < 10 && readSofar < metaFileSize; i++)
{
errno = 0;
bytes = metaFile->pread( p+readSofar,
readSofar,
metaFileSize-readSofar);
if (bytes < 0)
break;
readSofar += bytes;
}
if ( readSofar != metaFileSize )
{
int errRc = errno;
std::ostringstream oss;
oss << "Error reading bulk rollback meta-data file "
<< fMetaFileName << "; read/expect:" << readSofar << "/"
<< metaFileSize
<< "; err-" << errRc << "; " << strerror( errRc );
throw WeException( oss.str(), ERR_FILE_READ );
}
// put the data in a string stream
metaDataStream.str( std::string( p, metaFileSize ) );
buf.reset();
// read data
metaDataStream.getline( inBuf, BUF_SIZE );
if (!RBMetaWriter::verifyVersion4(inBuf))
{
std::ostringstream oss;
oss << "Invalid version record in meta-data file " << fMetaFileName
<< "; record-<" << inBuf << ">";
throw WeException( oss.str(), ERR_INVALID_PARAM );
}
}
} // end of namespace

View File

@ -0,0 +1,139 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/** @file */
#ifndef CONFIRM_HDFS_DBFILE_H
#define CONFIRM_HDFS_DBFILE_H
#include <string>
#include "IDBFileSystem.h"
#include "we_type.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
namespace WriteEngine
{
/** @brief Encapsulates logic to confirm and finalize (or abort) changes
* to an HDFS db file. Class should only be used for HDFS db files.
*
* For the HDFS db files that are modified, the new version of the file
* may be written to a file with an alternative suffix (like .tmp file).
* The confirmDbFileChange() function confirms that the work is complete,
* and that the new temporary file (ex: *.tmp) can replace the original file.
* After all the columns in a table have been confirmed (through calls to
* confirmDbFileChange()), then endDbFileChange() should be called to finish
* committing or aborting all the work.
*/
class ConfirmHdfsDbFile
{
public:
EXPORT ConfirmHdfsDbFile( );
EXPORT ~ConfirmHdfsDbFile( );
/** @brief Confirm changes to the specified db file
* @param backUpFileType Backup file type to confirm. Types:
* "rlc" - reallocated chunk file
* "tmp" - updated db file
* @param filename Name of db file to be confirmed.
* @param errMsg (out) Error msg associated with a bad return code
* @return Returns NO_ERROR if call is successful
*/
EXPORT int confirmDbFileChange( const std::string& backUpFileType,
const std::string& filename,
std::string& errMsg ) const;
/** @brief Finalize changes to the specified db file
*
* If success flag is true:
* The old version of the db file is deleted.
* If success flag is false:
* The old version is retained, and any temporary file with pending
* changes is deleted.
*
* @param backUpFileType Backup file type to finalize. Types:
* "rlc" - reallocated chunk file
* "tmp" - updated db file
* @param filename Name of db file to be finalized.
* @param success Final success/fail status of db file changes
* @param errMsg (out) Error msg associated with a bad return code
* @return Returns NO_ERROR if call is successful
*/
EXPORT int endDbFileChange( const std::string& backUpFileType,
const std::string& filename,
bool success,
std::string& errMsg ) const;
/** @brief Confirm changes to the db files modified for tableOID
*
* The HWM db file for each DBRoot, as listed in the bulk rollback meta
* data file (for the specified tableOID), is confirmed.
*
* @param tableOID Table that has changes to be confirmed
* @param errMsg (out) Error msg associated with a bad return code
* @return Returns NO_ERROR if call is successful
*/
EXPORT int confirmDbFileListFromMetaFile( OID tableOID,
std::string& errMsg );
/** @brief Finalize changes to the db files modified for tableOID
*
* The HWM db file for each DBRoot, as listed in the bulk rollback meta
* data file (for the specified tableOID), is finalized.
*
* If success flag is true:
* The old version of the db files are deleted.
* If success flag is false:
* The old versions are retained, and any temporary files with pending
* changes are deleted.
*
* @param tableOID Table that has changes to be confirmed
* @param errMsg (out) Error msg associated with a bad return code
* @return Returns NO_ERROR if call is successful
*/
EXPORT int endDbFileListFromMetaFile( OID tableOID,
bool success,
std::string& errMsg );
private:
void openMetaDataFile( OID tableOID,
uint16_t dbRoot,
std::istringstream& metaDataStream );
void confirmDbFiles( std::istringstream& metaDataStream ) const;
void confirmColumnDbFile( const char* inBuf ) const;
void confirmDctnryStoreDbFile( const char* inBuf ) const;
void endDbFiles( std::istringstream& metaDataStream, bool success ) const;
void endColumnDbFile( const char* inBuf, bool success ) const;
void endDctnryStoreDbFile( const char* inBuf, bool success ) const;
idbdatafile::IDBFileSystem& fFs;
std::string fMetaFileName;
};
} // end of namespace
#undef EXPORT
#endif // CONFIRM_HDFS_DBFILE_H

View File

@ -0,0 +1,824 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_convertor.cpp 4726 2013-08-07 03:38:36Z bwilkinson $
*
*******************************************************************************/
/** @file */
#include <unistd.h>
#include <limits>
#include <cstring>
#ifdef _MSC_VER
#include <cstdio>
#endif
#include "config.h"
#include "we_convertor.h"
using namespace std;
using namespace execplan;
namespace
{
const char DATE_TIME_FORMAT[] = "%04d-%02d-%02d %02d:%02d:%02d";
/*******************************************************************************
* DESCRIPTION:
* Takes an 8-bit value and converts it into a directory name.
* PARAMETERS:
* pBuffer(output) - a pointer to the output buffer
* blen (input) - the length of the output buffer (in bytes)
* val (input) - value to be used in the formatted name
* RETURN:
* the number of characters printed in the output buffer (not including
* the null terminator). -1 is returned if the input buffer pointer is NULL.
******************************************************************************/
int _doDir(char* pBuffer, int blen, unsigned int val)
{
int rc;
if (!pBuffer)
{
rc = -1;
} else {
rc = snprintf(pBuffer, blen, "%03u.dir", val);
pBuffer[blen-1] = (char)0;
}
return rc;
}
/*******************************************************************************
* DESCRIPTION:
* Takes an 8-bit value and converts it into a file name.
* PARAMETERS:
* pBuffer(output) - a pointer to the output buffer
* blen (input) - the length of the output buffer (in bytes)
* val (input) - value to be used in the formatted name
* RETURN:
* the number of characters printed in the output buffer (not including
* the null terminator). -1 is returned if the input buffer pointer is NULL.
******************************************************************************/
int _doFile(char* pBuffer, int blen, unsigned char val)
{
int rc;
if (!pBuffer)
{
rc = -1;
} else {
rc = snprintf(pBuffer, blen, "FILE%03d.cdf", val);
pBuffer[blen-1] = (char)0;
}
return rc;
}
}
namespace WriteEngine
{
struct Convertor::dmFilePathArgs_t
{
char* pDirA; // < OUT -- DirA's buffer
char* pDirB; // < OUT -- DirB's buffer
char* pDirC; // < OUT -- DirC's buffer
char* pDirD; // < OUT -- DirD's buffer
char* pDirE; // < OUT -- DirE's buffer
char* pFName; // < OUT -- Filename buffer
int ALen; // < IN -- Size in bytes of DirA's Buffer.
int BLen; // < IN -- Size in bytes of DirB's Buffer.
int CLen; // < IN -- Size in bytes of DirC's Buffer.
int DLen; // < IN -- Size in bytes of DirD's Buffer.
int ELen; // < IN -- Size in bytes of DirE's Buffer.
int FNLen; // < IN -- Size in bytes of Filename's Buffer.
int Arc; // < OUT -- result code for formatting DirA.
int Brc; // < OUT -- result code for formatting DirB.
int Crc; // < OUT -- result code for formatting DirC.
int Drc; // < OUT -- result code for formatting DirD.
int Erc; // < OUT -- result code for formatting DirE.
int FNrc; // < OUT -- result code for formatting Filename.
};
/*******************************************************************************
* DESCRIPTION:
* Get time string
* PARAMETERS:
* none
* RETURN:
* time string
******************************************************************************/
/* static */
const std::string Convertor::getTimeStr()
{
char buf[sizeof(DATE_TIME_FORMAT)+10] = {0};
time_t curTime = time(NULL);
struct tm pTime;
localtime_r(&curTime, &pTime);
string timeStr;
snprintf(buf, sizeof(buf), DATE_TIME_FORMAT, pTime.tm_year + 1900,
pTime.tm_mon + 1, pTime.tm_mday,
pTime.tm_hour, pTime.tm_min, pTime.tm_sec);
timeStr = buf;
return timeStr;
}
/*******************************************************************************
* DESCRIPTION:
* Convert int value to string
* PARAMETERS:
* val - value
* RETURN:
* string
******************************************************************************/
/* static */
const std::string Convertor::int2Str(int val)
{
char buf[12];
string myStr;
snprintf(buf, sizeof(buf), "%d", val);
myStr = buf;
return myStr;
}
/*******************************************************************************
* DESCRIPTION:
* Convert a numeric string to a decimal long long, given the specified
* scale. errno should be checked upon return from this function to see
* if it is set to ERANGE, meaning the value was out of range.
* PARAMETERS:
* field - string to be interpreted
* fieldLength - length of "field"
* scale - decimal scale value to be used to parse "field"
* RETURN:
* converted long long for specified "field"
******************************************************************************/
/* static */
long long Convertor::convertDecimalString(
const char* field,
int fieldLength,
int scale )
{
long long llVal = 0;
int nDigitsBeforeDecPt = 0;
int nDigitsAfterDecPt = 0;
long long roundUp = 0; //@bug 3405 round off decimal column values
// Determine the number of digits before and after the decimal point
char* posDecPt = (char*)memchr(field, '.', fieldLength);
if (posDecPt)
{
nDigitsBeforeDecPt = posDecPt - field;
nDigitsAfterDecPt = fieldLength - nDigitsBeforeDecPt - 1;
//@bug 3405 round off decimal column values
// We look at the scale+1 digit to see if we need to round up.
if (nDigitsAfterDecPt > scale)
{
char roundOffDigit = *(posDecPt + 1 + scale);
if ( (roundOffDigit > '4') &&
(roundOffDigit <='9') ) // round up
{
roundUp = 1;
// We can't just use the sign of llVal to determine whether to
// add +1 or -1, because if we read in -0.005 with scale 2, we
// end up parsing "-0.00", which yields 0; meaning we lose the
// sign. So better (though maybe slower) to look for any lead-
// ing negative sign in the input string.
for (int k=0; k<fieldLength; k++)
{
if (!isspace(field[k]))
{
if (field[k] == '-')
roundUp = -1;
break;
}
}
}
}
}
else
{
nDigitsBeforeDecPt = fieldLength;
nDigitsAfterDecPt = 0;
}
// Strip out the decimal point by stringing together
// the digits before and after the decimal point.
char* data = (char*)alloca(nDigitsBeforeDecPt + scale + 1);
memcpy(data, field, nDigitsBeforeDecPt);
if (nDigitsAfterDecPt)
{
if (scale > nDigitsAfterDecPt)
memcpy(data + nDigitsBeforeDecPt,
field + nDigitsBeforeDecPt + 1,
nDigitsAfterDecPt);
else // (scale <= nDigitsAfterDecPt)
memcpy(data + nDigitsBeforeDecPt,
field + nDigitsBeforeDecPt + 1,
scale);
}
// Add on any necessary zero padding at the end
if (scale > nDigitsAfterDecPt)
{
memset(data + nDigitsBeforeDecPt + nDigitsAfterDecPt,
'0',
scale - nDigitsAfterDecPt);
}
data[nDigitsBeforeDecPt + scale] = '\0';
// Convert our constructed decimal string back to a long long
//@bug 1814 Force strtoll to use base 10
errno = 0;
llVal = strtoll(data, 0, 10);
//@bug 3405 round off decimal values
if ((roundUp) && (errno == 0))
llVal += roundUp;
return llVal;
}
/*******************************************************************************
* DESCRIPTION:
* Convert an oid to a filename (with partition and segment number
* in the filepath.
* PARAMETERS:
* fid - fid
* fullFileName - file name
* dbDirName - components of fullFileName
* partition - partition number to be in used in filepath
* segment - segment number to be used in filename
* RETURN:
* NO_ERROR if success, other if fail
******************************************************************************/
/* static */
int Convertor::oid2FileName(FID fid,
char* fullFileName,
char dbDirName[][MAX_DB_DIR_NAME_SIZE],
uint32_t partition,
uint16_t segment)
{
dmFilePathArgs_t args;
int rc;
char aBuff[MAX_DB_DIR_NAME_SIZE];
char bBuff[MAX_DB_DIR_NAME_SIZE];
char cBuff[MAX_DB_DIR_NAME_SIZE];
char dBuff[MAX_DB_DIR_NAME_SIZE];
char eBuff[MAX_DB_DIR_NAME_SIZE];
char fnBuff[MAX_DB_DIR_NAME_SIZE];
args.pDirA = aBuff;
args.pDirB = bBuff;
args.pDirC = cBuff;
args.pDirD = dBuff;
args.pDirE = eBuff;
args.pFName = fnBuff;
args.ALen = sizeof(aBuff);
args.BLen = sizeof(bBuff);
args.CLen = sizeof(cBuff);
args.DLen = sizeof(dBuff);
args.ELen = sizeof(eBuff);
args.FNLen = sizeof(fnBuff);
args.Arc = 0;
args.Brc = 0;
args.Crc = 0;
args.Drc = 0;
args.Erc = 0;
args.FNrc = 0;
RETURN_ON_WE_ERROR(
(rc = dmOid2FPath(fid, partition, segment, &args)),
ERR_DM_CONVERT_OID);
sprintf(fullFileName, "%s/%s/%s/%s/%s/%s", args.pDirA,
args.pDirB, args.pDirC, args.pDirD, args.pDirE, args.pFName);
strcpy(dbDirName[0], args.pDirA);
strcpy(dbDirName[1], args.pDirB);
strcpy(dbDirName[2], args.pDirC);
strcpy(dbDirName[3], args.pDirD);
strcpy(dbDirName[4], args.pDirE);
strcpy(dbDirName[5], args.pFName);
// std::cout << "OID: " << fid <<
// " mapping to file: " << fullFileName <<std::endl;
return NO_ERROR;
}
/*******************************************************************************
* DESCRIPTION:
* Map specified errno to the associated error message string.
* PARAMETERS:
* errNum - errno to be converted
* errString-(output) error message string associated with errNum
* RETURN:
* none
******************************************************************************/
/* static */
void Convertor::mapErrnoToString(int errNum, std::string& errString)
{
char errnoMsgBuf[1024];
#if STRERROR_R_CHAR_P
char* errnoMsg = strerror_r(errNum, errnoMsgBuf, sizeof(errnoMsgBuf));
if (errnoMsg)
errString = errnoMsg;
else
errString.clear();
#else
int errnoMsg = strerror_r(errNum, errnoMsgBuf, sizeof(errnoMsgBuf));
if (errnoMsg == 0)
errString = errnoMsgBuf;
else
errString.clear();
#endif
}
/*******************************************************************************
* DESCRIPTION:
* Convert specified ColDataType to internal storage type (ColType).
* PARAMETERS:
* dataType - Interface data-type
* internalType - Internal data-type used for storing
* RETURN:
* none
******************************************************************************/
/* static */
void Convertor::convertColType(CalpontSystemCatalog::ColDataType dataType,
ColType& internalType, bool isToken)
{
if (isToken)
{
internalType = WriteEngine::WR_TOKEN;
return;
}
switch(dataType) {
// Map BIT and TINYINT to WR_BYTE
case CalpontSystemCatalog::BIT :
case CalpontSystemCatalog::TINYINT :
internalType = WriteEngine::WR_BYTE; break;
// Map SMALLINT to WR_SHORT
case CalpontSystemCatalog::SMALLINT :
internalType = WriteEngine::WR_SHORT; break;
// Map MEDINT, INT, and DATE to WR_INT
case CalpontSystemCatalog::MEDINT :
case CalpontSystemCatalog::INT :
case CalpontSystemCatalog::DATE :
internalType = WriteEngine::WR_INT; break;
// Map FLOAT and UFLOAT to WR_FLOAT
case CalpontSystemCatalog::FLOAT :
case CalpontSystemCatalog::UFLOAT:
internalType = WriteEngine::WR_FLOAT; break;
// Map BIGINT and DATETIME to WR_LONGLONG
case CalpontSystemCatalog::BIGINT :
case CalpontSystemCatalog::DATETIME :
internalType = WriteEngine::WR_LONGLONG; break;
// Map DOUBLE and UDOUBLE to WR_DOUBLE
case CalpontSystemCatalog::DOUBLE :
case CalpontSystemCatalog::UDOUBLE:
internalType = WriteEngine::WR_DOUBLE; break;
// Map BLOB to WR_BLOB
case CalpontSystemCatalog::BLOB :
internalType = WriteEngine::WR_BLOB; break;
// Map VARBINARY to WR_VARBINARY
case CalpontSystemCatalog::VARBINARY:
internalType = WriteEngine::WR_VARBINARY; break;
// Map DECIMAL to applicable WR_CHAR
// We can't map them to their proper int size, since in this version
// of convertColType(), we don't know what that is. Hopefully
// this is never used for DECIMAL.
case CalpontSystemCatalog::DECIMAL :
case CalpontSystemCatalog::UDECIMAL:
// Map CHAR, VARCHAR, and CLOB to WR_CHAR
case CalpontSystemCatalog::CHAR :
case CalpontSystemCatalog::VARCHAR :
case CalpontSystemCatalog::CLOB :
internalType = WriteEngine::WR_CHAR; break;
// Map UTINYINT to WR_UBYTE
case CalpontSystemCatalog::UTINYINT:
internalType = WriteEngine::WR_UBYTE; break;
// Map USMALLINT to WR_USHORT
case CalpontSystemCatalog::USMALLINT:
internalType = WriteEngine::WR_USHORT; break;
// Map UMEDINT and UINT to WR_UINT
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
internalType = WriteEngine::WR_UINT; break;
// Map UBIGINT to WR_ULONGLONG
case CalpontSystemCatalog::UBIGINT:
internalType = WriteEngine::WR_ULONGLONG; break;
default:
internalType = WriteEngine::WR_CHAR; break;
}
}
/*******************************************************************************
* DESCRIPTION:
* Convert specified internal storage type (ColType) to ColDataType. Since
* there is a one to many relationship, we choose the most general.
* PARAMETERS:
* internalType - Internal data-type used for storing
* dataType - Interface data-type
* RETURN:
* none
******************************************************************************/
/* static */
void Convertor::convertWEColType(ColType internalType,
CalpontSystemCatalog::ColDataType& dataType)
{
switch(internalType)
{
// Map BIT and TINYINT to WR_BYTE
case WriteEngine::WR_BYTE :
dataType = CalpontSystemCatalog::TINYINT; break;
// Map SMALLINT to WR_SHORT
case WriteEngine::WR_SHORT :
dataType = CalpontSystemCatalog::SMALLINT; break;
// Map MEDINT, INT, and DATE to WR_INT
case WriteEngine::WR_INT :
dataType = CalpontSystemCatalog::INT; break;
// Map FLOAT and UFLOAT to WR_FLOAT
case WriteEngine::WR_FLOAT:
dataType = CalpontSystemCatalog::FLOAT; break;
// Map BIGINT and DATETIME to WR_LONGLONG
case WriteEngine::WR_LONGLONG :
dataType = CalpontSystemCatalog::BIGINT; break;
// Map DOUBLE and UDOUBLE to WR_DOUBLE
case WriteEngine::WR_DOUBLE :
dataType = CalpontSystemCatalog::DOUBLE; break;
// Map BLOB to WR_BLOB
case WriteEngine::WR_BLOB :
dataType = CalpontSystemCatalog::BLOB; break;
// Map VARBINARY to WR_VARBINARY
case WriteEngine::WR_VARBINARY:
dataType = CalpontSystemCatalog::VARBINARY; break;
// Map CHAR, VARCHAR, and CLOB to WR_CHAR
case WriteEngine::WR_CHAR :
dataType = CalpontSystemCatalog::CHAR; break;
// Map UTINYINT to WR_UBYTE
case WriteEngine::WR_UBYTE:
dataType = CalpontSystemCatalog::UTINYINT; break;
// Map USMALLINT to WR_USHORT
case WriteEngine::WR_USHORT:
dataType = CalpontSystemCatalog::USMALLINT; break;
// Map UMEDINT and UINT to WR_UINT
case WriteEngine::WR_UINT:
dataType = CalpontSystemCatalog::UINT; break;
// Map UBIGINT to WR_ULONGLONG
case WriteEngine::WR_ULONGLONG:
dataType = CalpontSystemCatalog::UBIGINT; break;
default:
dataType = CalpontSystemCatalog::CHAR; break;
}
}
/*******************************************************************************
* DESCRIPTION:
* Convert curStruct from an interface-type struct to an internal-type
* struct. curStruct is handled as a ColStruct.
* PARAMETERS:
* curStruct - column struct to be initialized
* RETURN:
* none
******************************************************************************/
/* static */
void Convertor::convertColType(ColStruct* curStruct)
{
CalpontSystemCatalog::ColDataType dataType // This will be updated later,
= CalpontSystemCatalog::CHAR; // CHAR used only for initialization.
ColType* internalType = NULL;
bool bTokenFlag = false;
int* width = NULL;
dataType = curStruct->colDataType;
internalType = &(curStruct->colType);
bTokenFlag = curStruct->tokenFlag;
width = &(curStruct->colWidth);
switch(dataType) {
// Map BIT and TINYINT to WR_BYTE
case CalpontSystemCatalog::BIT :
case CalpontSystemCatalog::TINYINT :
*internalType = WriteEngine::WR_BYTE; break;
// Map SMALLINT to WR_SHORT
case CalpontSystemCatalog::SMALLINT :
*internalType = WriteEngine::WR_SHORT; break;
// Map MEDINT, INT, and DATE to WR_INT
case CalpontSystemCatalog::MEDINT :
case CalpontSystemCatalog::INT :
case CalpontSystemCatalog::DATE :
*internalType = WriteEngine::WR_INT; break;
// Map FLOAT and UFLOAT to WR_FLOAT
case CalpontSystemCatalog::FLOAT :
case CalpontSystemCatalog::UFLOAT :
*internalType = WriteEngine::WR_FLOAT; break;
// Map BIGINT and DATETIME to WR_LONGLONG
case CalpontSystemCatalog::BIGINT :
case CalpontSystemCatalog::DATETIME :
*internalType = WriteEngine::WR_LONGLONG; break;
// Map DOUBLE and UDOUBLE to WR_DOUBLE
case CalpontSystemCatalog::DOUBLE :
case CalpontSystemCatalog::UDOUBLE :
*internalType = WriteEngine::WR_DOUBLE; break;
// Map DECIMAL to applicable integer type
case CalpontSystemCatalog::DECIMAL :
case CalpontSystemCatalog::UDECIMAL :
{
switch (*width)
{
case 1 : *internalType = WriteEngine::WR_BYTE; break;
case 2 : *internalType = WriteEngine::WR_SHORT; break;
case 4 : *internalType = WriteEngine::WR_INT; break;
default: *internalType = WriteEngine::WR_LONGLONG; break;
}
break;
}
// Map BLOB to WR_BLOB
case CalpontSystemCatalog::BLOB :
*internalType = WriteEngine::WR_BLOB; break;
// Map VARBINARY to WR_VARBINARY
case CalpontSystemCatalog::VARBINARY:
*internalType = WriteEngine::WR_VARBINARY; break;
// Map CHAR, VARCHAR, and CLOB to WR_CHAR
case CalpontSystemCatalog::CHAR :
case CalpontSystemCatalog::VARCHAR :
case CalpontSystemCatalog::CLOB :
*internalType = WriteEngine::WR_CHAR; break;
// Map UTINYINT to WR_UBYTE
case CalpontSystemCatalog::UTINYINT:
*internalType = WriteEngine::WR_UBYTE; break;
// Map USMALLINT to WR_USHORT
case CalpontSystemCatalog::USMALLINT:
*internalType = WriteEngine::WR_USHORT; break;
// Map UMEDINT and UINT to WR_UINT
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
*internalType = WriteEngine::WR_UINT; break;
// Map UBIGINT to WR_ULONGLONG
case CalpontSystemCatalog::UBIGINT:
*internalType = WriteEngine::WR_ULONGLONG; break;
default:
*internalType = WriteEngine::WR_CHAR; break;
}
if (bTokenFlag) // token overwrite any other types
*internalType = WriteEngine::WR_TOKEN;
// check whether width is in sync with the requirement
*width = getCorrectRowWidth(dataType, *width);
// This is the patch for the decimal thing, override
// if (dataType == CalpontSystemCatalog::DECIMAL)
// {
// *internalType = *width <= 4 ?
// WriteEngine::WR_INT : WriteEngine::WR_LONGLONG;
// }
}
/*******************************************************************************
* DESCRIPTION:
* Get the correct width for a row
* PARAMETERS:
* dataType - data type
* width - data width in byte
* RETURN:
* emptyVal - the value of empty row
******************************************************************************/
/* static */
int Convertor::getCorrectRowWidth(CalpontSystemCatalog::ColDataType dataType, int width)
{
int offset, newWidth = 4;
switch(dataType) {
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::UTINYINT:
newWidth = 1; break;
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::USMALLINT:
newWidth = 2; break;
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
newWidth = 4; break;
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::UBIGINT:
newWidth = 8; break;
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
newWidth = 4; break;
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
newWidth = 8; break;
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
if (width == 1)
newWidth = 1;
else if (width == 2)
newWidth = 2;
else if (width <= 4)
newWidth = 4;
else
newWidth = 8;
break;
case CalpontSystemCatalog::DATE:
newWidth = 4; break;
case CalpontSystemCatalog::DATETIME:
newWidth = 8; break;
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
case CalpontSystemCatalog::VARBINARY: // treat same as varchar for now
default:
offset = (dataType == CalpontSystemCatalog::VARCHAR)? -1 : 0;
newWidth = 1;
if (width == (2 + offset))
newWidth = 2;
else if (width >= (3 + offset) && width <= (4 + offset))
newWidth = 4;
else if (width >= (5 + offset))
newWidth = 8;
break;
}
return newWidth;
}
/*******************************************************************************
* DESCRIPTION:
* Converts an OID into a group if directories and a filename.
*
* This function takes a 32-bit Object ID (OID). If DLen is 0, then the
* OID is converted into 3 hierarchical directory names and a filename.
* If DLen is >0 then the OID is converted into 5 hierarchical directory
* names and a filename (using the partition and segment as additional
* input into the filepath. The actual location
* of the file is <DBRoot>/<DirA>/<DirB>/<DirC>/<FName>, or
* <DBRoot>/<DirA>/<DirB>/<DirC>/<DirD>/<part#>/<segFName>. The <DBRoot>
* entry must be pre-pended by the calling application after calling
* this function. The value for <DBRoot> is stored in the Calpont.xml
* configuration file.
*
* PARAMETERS:
* oid INPUT -- The Object Id.
* partition INPUT -- partition to be included in filepath.
* segment INPUT -- segment to be included in filepath.
* dmFilePathArgs* INPUT/OUTPUT -- Points to a buffer structure
*
* RETURN:
* return 0 if everything went OK. -1 if an error occured. Two
* kinds of errors are possible:
*
* - a null pointer was passed in
* - truncation occured.
*
* If a null buffer pointer is passed in, a return code
* of -1 will be returned FOR THAT BUFFER.
*
* Truncation can occur if the buffer length specified in
* dmFilePathArgs is too small.
*
* If a buffer's return code is not zero, the appropriate
* return code in dmfilePathArgs can be examined. If a
* buffer's return code is be less than zero, the
* corresponding buffer pointer was NULL. If it is greater
* or equal to the buffer's length argument, length is too small
******************************************************************************/
/*static*/
int Convertor::dmOid2FPath(uint32_t oid, uint32_t partition, uint32_t segment,
dmFilePathArgs_t* pArgs)
{
pArgs->Arc = _doDir(
pArgs->pDirA,
pArgs->ALen,
(unsigned int)oid>>24);
pArgs->Brc = _doDir(
pArgs->pDirB,
pArgs->BLen,
(unsigned int)(oid&0x00ff0000)>>16);
pArgs->Crc = _doDir(
pArgs->pDirC,
pArgs->CLen,
(unsigned int)(oid&0x0000ff00)>>8);
// include partition and seg num in the file path if they are present
if (pArgs->DLen > 0)
{
pArgs->Drc = _doDir(
pArgs->pDirD,
pArgs->DLen,
(unsigned int)(oid&0x000000ff));
pArgs->Erc = _doDir(
pArgs->pDirE,
pArgs->ELen,
partition);
pArgs->FNrc = _doFile(
pArgs->pFName,
pArgs->FNLen,
segment);
if ( (pArgs->Drc < 0) ||
(pArgs->Erc < 0) )
return -1;
if ( (pArgs->Drc >= pArgs->ALen) ||
(pArgs->Erc >= pArgs->ALen) )
return -1;
}
else
{
pArgs->FNrc = _doFile(
pArgs->pFName,
pArgs->FNLen,
(unsigned int)(oid&0x000000ff));
}
if ( (pArgs->Arc < 0) ||
(pArgs->Brc < 0) ||
(pArgs->Crc < 0) ||
(pArgs->FNrc < 0) )
return -1;
if ( (pArgs->Arc >= pArgs->ALen) ||
(pArgs->Brc >= pArgs->BLen) ||
(pArgs->Crc >= pArgs->CLen) ||
(pArgs->FNrc >= pArgs->FNLen) )
return -1;
else
return 0;
}
} //end of namespace

View File

@ -0,0 +1,148 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_convertor.h 4726 2013-08-07 03:38:36Z bwilkinson $
*
*******************************************************************************/
/** @file */
#ifndef _WE_CONVERTOR_H_
#define _WE_CONVERTOR_H_
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <iostream>
#include <fstream>
#include "we_obj.h"
#include "we_config.h"
#include "calpontsystemcatalog.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
/** Class Convertor */
class Convertor
{
public:
/**
* @brief Default Constructor
*/
Convertor(){}
/**
* @brief Destructor
*/
~Convertor(){}
/**
* @brief Get date/time string based on current date and time
*/
EXPORT static const std::string getTimeStr();
/**
* @brief Convert specified integer value to a string
*
* @param val Integer value to be converted to a string
*/
EXPORT static const std::string int2Str(int val);
/**
* @brief Convert an oid to a full file name (with partition and segment
* being included in the filename). This is used for all column and
* dictionary store db files. If dealing with a version buffer file,
* a partition and segment number of 0 should be used.
*/
EXPORT static int oid2FileName(FID fid, char* fullFileName,
char dbDirName[][MAX_DB_DIR_NAME_SIZE],
uint32_t partition, uint16_t segment);
/**
* @brief Convert specified errno to associated error msg string
*
* @param errNum System errno to be converted.
* @param errString Error msg string associated with the specified errno.
*/
EXPORT static void mapErrnoToString(int errNum, std::string& errString);
/**
* @brief Convert specified ColDataType to internal storage type (ColType)
*
* @param dataType Interface data-type
* @param internalType Internal data-type used for storing
*/
//BUG931
EXPORT static void convertColType(execplan::CalpontSystemCatalog::ColDataType dataType,
ColType& internalType, bool isToken=false);
/**
* @brief Convert specified internal storage type (ColType) to
* ColDataType
*
* @param internalType Internal data-type used for storing
* @param dataType Interface data-type
*/
EXPORT static void convertWEColType(ColType internalType,
execplan::CalpontSystemCatalog::ColDataType& dataType);
/**
* @brief Convert interface column type to a internal column type.
* curStruct is interpreted as a ColStruct.
*/
EXPORT static void convertColType(ColStruct* curStruct);
/*
* @brief Get the correct width for a row
*/
EXPORT static int getCorrectRowWidth( execplan::CalpontSystemCatalog::ColDataType dataType, int width );
/*
* @brief Convert a Decimal string to it's equivalent integer value.
* errno can be checked upon return to see if input value was
* out of range (ERANGE).
*
* field decimal string to be converted
* fieldLengh length of "field" in bytes
* scale decimal scale to be applied to value
*/
EXPORT static long long convertDecimalString ( const char* field,
int fieldLength,
int scale );
private:
struct dmFilePathArgs_t;
static int dmOid2FPath(uint32_t oid, uint32_t partition, uint32_t segment,
dmFilePathArgs_t* pArgs);
};
} //end of namespace
#undef EXPORT
#endif // _WE_CONVERTOR_H_

View File

@ -0,0 +1,507 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id: we_dbfileop.cpp 4737 2013-08-14 20:45:46Z bwilkinson $
/** @file */
#include <unistd.h>
#include <stdio.h>
#include <cstring>
using namespace std;
#include "we_chunkmanager.h"
#include "we_dbfileop.h"
#include "we_stats.h"
#include "IDBDataFile.h"
using namespace idbdatafile;
using namespace BRM;
namespace WriteEngine
{
/**
* Constructor
*/
DbFileOp::DbFileOp() : m_chunkManager(NULL)
{}
/**
* Default Destructor
*/
DbFileOp::~DbFileOp()
{}
/***********************************************************
* DESCRIPTION:
* flush the cache
* PARAMETERS:
* none
* RETURN:
* NO_ERROR if success, otherwise if fail
***********************************************************/
int DbFileOp::flushCache()
{
BlockBuffer* curBuf;
if( !Cache::getUseCache() )
return NO_ERROR;
for( CacheMapIt it = Cache::m_writeList->begin();
it != Cache::m_writeList->end(); it++ ) {
curBuf = it->second;
RETURN_ON_ERROR( writeDBFile( (*curBuf).cb.file.pFile,
(*curBuf).block.data,
(*curBuf).block.lbid ) );
}
RETURN_ON_ERROR( Cache::flushCache() );
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* get an entry within a sub block
* NOTE: the difference with readSubBlockEntry is that
* getSubBlockEntry only works for buffer while
* readSubBlockEntry works for file and block
* PARAMETERS:
* blockBuf - the block buffer
* sbid - sub block id
* entryNo - entry no within sub block
* width - width in bytes
* pStruct - sturcture pointer
* RETURN:
* none
***********************************************************/
void DbFileOp::getSubBlockEntry( unsigned char* blockBuf,
const int sbid, const int entryNo,
const int width, void* pStruct )
{
unsigned char* pBlock;
pBlock = blockBuf + BYTE_PER_SUBBLOCK * sbid + entryNo *MAX_COLUMN_BOUNDARY;
memcpy( pStruct, pBlock, width );
}
/***********************************************************
* DESCRIPTION:
* Read a block from a file at specified location
* PARAMETERS:
* pFile - file handle
* readBuf - read buffer
* fbo - file block offset
* RETURN:
* NO_ERROR if success
* other number if something wrong
***********************************************************/
int DbFileOp::readDBFile( IDBDataFile* pFile,
unsigned char* readBuf,
const uint64_t lbid,
const bool isFbo )
{
long long fboOffset = 0;
if( !isFbo ) {
RETURN_ON_ERROR( setFileOffsetBlock( pFile, lbid ) );
}
else {
fboOffset = (lbid)*(long)BYTE_PER_BLOCK;
RETURN_ON_ERROR( setFileOffset( pFile, fboOffset ) );
}
return readFile( pFile, readBuf, BYTE_PER_BLOCK );
}
int DbFileOp::readDBFile( IDBDataFile* pFile,
DataBlock* block,
const uint64_t lbid,
const bool isFbo )
{
block->dirty = false;
block->no = lbid;
Stats::incIoBlockRead();
return readDBFile( pFile, block->data, lbid, isFbo );
}
int DbFileOp::readDBFile( CommBlock& cb,
unsigned char* readBuf,
const uint64_t lbid )
{
CacheKey key;
if( Cache::getUseCache() )
{
if( Cache::cacheKeyExist( cb.file.oid, lbid ) ) {
key = Cache::getCacheKey( cb.file.oid, lbid );
RETURN_ON_ERROR( Cache::loadCacheBlock( key, readBuf ) );
return NO_ERROR;
}
}
RETURN_ON_ERROR( readDBFile( cb.file.pFile, readBuf, lbid ) );
if( Cache::getUseCache() )
{
int fbo = lbid;
uint16_t dbRoot;
uint32_t partition;
uint16_t segment;
RETURN_ON_ERROR( BRMWrapper::getInstance()->getFboOffset(
lbid, dbRoot, partition, segment, fbo ) );
if( Cache::getListSize( FREE_LIST ) == 0 ) {
if ( isDebug( DEBUG_1 ) ) {
printf( "\nBefore flushing cache " );
Cache::printCacheList();
}
// flush cache to give up more space
RETURN_ON_ERROR( flushCache() );
if ( isDebug( DEBUG_1 ) ) {
printf( "\nAfter flushing cache " );
Cache::printCacheList();
}
}
RETURN_ON_ERROR( Cache::insertLRUList( cb, lbid, fbo, readBuf ) );
}
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION: No change, old signature 10/17/06
* Read an entry within a sub block from a file
* NOTE: the difference with getSubBlockEntry is that
* getSubBlockEntry only works for buffer while
* readSubBlockEntry works for file and block
* PARAMETERS:
* pFile - file handler
* block - the block structure
* fbo - file block offset
* sbid - sub block id
* entryNo - entry no within sub block
* width - width in bytes
* pStruct - sturcture pointer
* RETURN:
* NO_ERROR if success
* other number if something wrong
***********************************************************/
const int DbFileOp::readSubBlockEntry( IDBDataFile* pFile, DataBlock* block,
const uint64_t lbid, const int sbid,
const int entryNo, const int width,
void* pStruct )
{
RETURN_ON_ERROR( readDBFile( pFile, block->data, lbid ) );
getSubBlockEntry( block->data, sbid, entryNo, width, pStruct );
return NO_ERROR;
}
const int DbFileOp::readSubBlockEntry( CommBlock& cb, DataBlock* block,
const uint64_t lbid, const int sbid,
const int entryNo, const int width,
void* pStruct )
{
RETURN_ON_ERROR( readDBFile( cb, block->data, lbid ) );
getSubBlockEntry( block->data, sbid, entryNo, width, pStruct );
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Set an entry within a sub block
* NOTE: the difference with writeSubBlockEntry is that
* setSubBlockEntry only works for buffer while
* writeSubBlockEntry works for file and block
* PARAMETERS:
* blockBuf - the block buffer
* sbid - sub block id
* entryNo - entry no within sub block
* width - width in bytes
* pStruct - sturcture pointer
* RETURN:
* none
***********************************************************/
void DbFileOp::setSubBlockEntry( unsigned char* blockBuf, const int sbid,
const int entryNo, const int width,
const void* pStruct )
{
unsigned char* pBlock;
pBlock = blockBuf + BYTE_PER_SUBBLOCK * sbid + entryNo *MAX_COLUMN_BOUNDARY;
memcpy( pBlock, pStruct, width );
}
/***********************************************************
* DESCRIPTION:
* Write a number of blocks to the file at specified location
* PARAMETERS:
* pFile - file handle
* writeBuf - write buffer
* fbo - file block offset
* numOfBlock - total number of file block offset
* RETURN:
* NO_ERROR if success
* other number if something wrong
***********************************************************/
int DbFileOp::writeDBFile( CommBlock& cb, const unsigned char* writeBuf,
const uint64_t lbid, const int numOfBlock )
{
CacheKey key;
int ret;
if( Cache::getUseCache() )
{
if( Cache::cacheKeyExist( cb.file.oid, lbid ) ) {
key = Cache::getCacheKey( cb.file.oid, lbid );
RETURN_ON_ERROR( Cache::modifyCacheBlock( key, writeBuf ) );
return NO_ERROR;
}
}
if (BRMWrapper::getUseVb())
{
RETURN_ON_ERROR( writeVB( cb.file.pFile, cb.file.oid, lbid ) );
}
ret = writeDBFile( cb.file.pFile, writeBuf, lbid, numOfBlock );
if (BRMWrapper::getUseVb())
{
LBIDRange_v ranges;
LBIDRange range;
range.start = lbid;
range.size = 1;
ranges.push_back(range);
BRMWrapper::getInstance()->writeVBEnd(getTransId(), ranges);
}
return ret;
}
int DbFileOp::writeDBFileNoVBCache(CommBlock & cb,
const unsigned char * writeBuf,
const int fbo,
const int numOfBlock)
{
return writeDBFileNoVBCache( cb.file.pFile, writeBuf, fbo, numOfBlock );
}
/***********************************************************
* DESCRIPTION:
* Core function for writing data w/o using VB cache
* (bulk load dictionary store inserts)
***********************************************************/
int DbFileOp::writeDBFileNoVBCache( IDBDataFile* pFile,
const unsigned char* writeBuf,
const int fbo,
const int numOfBlock )
{
#ifdef PROFILE
// This function is only used by bulk load for dictionary store files,
// so we log as such.
Stats::startParseEvent(WE_STATS_WRITE_DCT);
#endif
for( int i = 0; i < numOfBlock; i++ ) {
Stats::incIoBlockWrite();
RETURN_ON_ERROR( writeFile( pFile, writeBuf, BYTE_PER_BLOCK ) );
}
#ifdef PROFILE
Stats::stopParseEvent(WE_STATS_WRITE_DCT);
#endif
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Core function for writing data using VB cache
***********************************************************/
int DbFileOp::writeDBFile( IDBDataFile* pFile, const unsigned char* writeBuf,
const uint64_t lbid, const int numOfBlock )
{
RETURN_ON_ERROR( setFileOffsetBlock( pFile, lbid ) );
for( int i = 0; i < numOfBlock; i++ ) {
Stats::incIoBlockWrite();
RETURN_ON_ERROR( writeFile( pFile, writeBuf, BYTE_PER_BLOCK ) );
}
return NO_ERROR;
}
// just don't have a good solution to consolidate with above functions
// Note: This is used with absolute FBO, no lbid involved
int DbFileOp::writeDBFileFbo(IDBDataFile* pFile, const unsigned char* writeBuf,
const uint64_t fbo, const int numOfBlock )
{
long long fboOffset = 0;
fboOffset = (fbo)*(long)BYTE_PER_BLOCK;
RETURN_ON_ERROR( setFileOffset( pFile, fboOffset ) );
for( int i = 0; i < numOfBlock; i++ ) {
Stats::incIoBlockWrite();
RETURN_ON_ERROR( writeFile( pFile, writeBuf, BYTE_PER_BLOCK ) );
}
return NO_ERROR;
}
/***********************************************************
* DESCRIPTION:
* Write an entry within a sub block to a file
* NOTE: the difference with getSubBlockEntry is that
* setSubBlockEntry only works for buffer while
* writeSubBlockEntry works for file and block
* PARAMETERS:
* pFile - file handler
* block - the block structure
* fbo - file block offset
* sbid - sub block id
* entryNo - entry no within sub block
* width - width in bytes
* pStruct - sturcture pointer
* RETURN:
* NO_ERROR if success
* other number if something wrong
***********************************************************/
const int DbFileOp::writeSubBlockEntry( IDBDataFile* pFile, DataBlock* block,
const uint64_t lbid, const int sbid,
const int entryNo, const int width,
void* pStruct )
{
setSubBlockEntry( block->data, sbid, entryNo, width, pStruct );
block->dirty = false;
return writeDBFile( pFile, block->data, lbid );
}
const int DbFileOp::writeSubBlockEntry( CommBlock& cb, DataBlock* block,
const uint64_t lbid, const int sbid,
const int entryNo, const int width,
void* pStruct )
{
setSubBlockEntry( block->data, sbid, entryNo, width, pStruct );
block->dirty = false;
return writeDBFile( cb, block->data, lbid );
}
/***********************************************************
* DESCRIPTION:
* Write to version buffer
* PARAMETERS:
* oid - file oid
* lbid - lbid
* RETURN:
* NO_ERROR if success
* other number if something wrong
***********************************************************/
const int DbFileOp::writeVB( IDBDataFile* pFile, const OID oid, const uint64_t lbid )
{
if( !BRMWrapper::getUseVb() )
return NO_ERROR;
int rc;
TxnID transId = getTransId();
if (transId !=((TxnID)INVALID_NUM))
{
rc= BRMWrapper::getInstance()->writeVB( pFile,
(const VER_t)transId,
oid, lbid, this );
//@Bug 4671. The error is already logged by worker node.
/* if (rc != NO_ERROR)
{
char msg[2048];
snprintf(msg, 2048,
"we_dbfileop->BRMWrapper::getInstance()->writeVB "
"transId %i oid %i lbid "
#if __LP64__
"%lu"
#else
"%llu"
#endif
" Error Code %i", transId, oid, lbid, rc);
puts(msg);
{
logging::MessageLog ml(logging::LoggingID(19));
logging::Message m;
logging::Message::Args args;
args.add(msg);
m.format(args);
ml.logCriticalMessage(m);
}
return rc;
} */
return rc;
}
return NO_ERROR;
}
int DbFileOp::readDbBlocks(IDBDataFile* pFile,
unsigned char* readBuf,
uint64_t fbo,
size_t n)
{
if (m_chunkManager) {
return m_chunkManager->readBlocks(pFile, readBuf, fbo, n);
}
if (setFileOffset(pFile, fbo*BYTE_PER_BLOCK, SEEK_SET) != NO_ERROR)
return -1;
return pFile->read(readBuf, BYTE_PER_BLOCK * n) / BYTE_PER_BLOCK;
}
int DbFileOp::restoreBlock(IDBDataFile* pFile, const unsigned char* writeBuf, uint64_t fbo)
{
if (m_chunkManager)
return m_chunkManager->restoreBlock(pFile, writeBuf, fbo);
if (setFileOffset(pFile, fbo*BYTE_PER_BLOCK, SEEK_SET) != NO_ERROR)
return -1;
return pFile->write(writeBuf, BYTE_PER_BLOCK);
}
// @bug 5572 - HDFS usage: add *.tmp file backup flag
IDBDataFile* DbFileOp::getFilePtr(const Column& column, bool useTmpSuffix)
{
string filename;
return m_chunkManager->getFilePtr(column,
column.dataFile.fDbRoot,
column.dataFile.fPartition,
column.dataFile.fSegment,
filename,
"r+b",
column.colWidth,
useTmpSuffix);
}
} //end of namespace

View File

@ -0,0 +1,235 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id: we_dbfileop.h 4726 2013-08-07 03:38:36Z bwilkinson $
/** @file */
#ifndef _WE_DBFILEOP_H_
#define _WE_DBFILEOP_H_
#include "we_type.h"
#include "we_fileop.h"
#include "we_blockop.h"
#include "we_cache.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
// forward reference
class ChunkManager;
/** Class DbFileOp */
class DbFileOp : public FileOp
{
public:
/**
* @brief Constructor
*/
EXPORT DbFileOp();
/**
* @brief Default Destructor
*/
EXPORT virtual ~DbFileOp();
EXPORT virtual int flushCache();
/**
* @brief Get an entry within a subblock
*/
EXPORT void getSubBlockEntry( unsigned char* blockBuf,
const int sbid,
const int entryNo,
const int width,
void* pStruct ) ;
/**
* @brief Get an entry within a subblock using block information
*/
void getSubBlockEntry( DataBlock* block,
const int sbid,
const int entryNo,
const int width,
void* pStruct )
{ getSubBlockEntry( block->data, sbid, entryNo, width, pStruct );}
/**
* @brief Read DB file to a buffer
*/
EXPORT virtual int readDBFile( IDBDataFile* pFile,
unsigned char* readBuf,
const uint64_t lbid,
const bool isFbo = false );
EXPORT int readDBFile( CommBlock& cb,
unsigned char* readBuf,
const uint64_t lbid );
EXPORT int readDBFile( IDBDataFile* pFile,
DataBlock* block,
const uint64_t lbid,
const bool isFbo = false );
int readDBFile( CommBlock& cb,
DataBlock* block,
const uint64_t lbid )
{ return readDBFile( cb, block->data, lbid );}
/**
* @brief Get an entry within a subblock and also populate block buffer
*
*/
EXPORT const int readSubBlockEntry(IDBDataFile* pFile,
DataBlock* block,
const uint64_t lbid,
const int sbid,
const int entryNo,
const int width,
void* pStruct ) ;
EXPORT const int readSubBlockEntry(CommBlock& cb,
DataBlock* block,
const uint64_t lbid,
const int sbid,
const int entryNo,
const int width,
void* pStruct );
/**
* @brief Set an entry within a subblock
*/
EXPORT void setSubBlockEntry( unsigned char* blockBuf,
const int sbid,
const int entryNo,
const int width,
const void* pStruct ) ;
/**
* @brief Set an entry within a subblock using block information
*/
void setSubBlockEntry( DataBlock* block,
const int sbid,
const int entryNo,
const int width,
const void* pStruct )
{ block->dirty = true;
setSubBlockEntry( block->data, sbid, entryNo, width, pStruct ); }
/**
* @brief Lbid Write a buffer to a DB file
*/
EXPORT virtual int writeDBFile( IDBDataFile* pFile,
const unsigned char* writeBuf,
const uint64_t lbid,
const int numOfBlock = 1 );
EXPORT int writeDBFile( CommBlock& cb,
const unsigned char* writeBuf,
const uint64_t lbid,
const int numOfBlock = 1 );
/**
* @brief Write designated block(s) w/o writing to Version Buffer or cache.
*/
EXPORT int writeDBFileNoVBCache(CommBlock & cb,
const unsigned char * writeBuf,
const int fbo,
const int numOfBlock = 1);
EXPORT virtual int writeDBFileNoVBCache(IDBDataFile *pFile,
const unsigned char * writeBuf,
const int fbo,
const int numOfBlock = 1);
int writeDBFile( IDBDataFile* pFile,
DataBlock* block,
const uint64_t lbid )
{ block->dirty=false; return writeDBFile( pFile, block->data, lbid ); }
int writeDBFile( CommBlock& cb,
DataBlock* block,
const uint64_t lbid )
{ return writeDBFile( cb, block->data, lbid ); }
EXPORT virtual int writeDBFileFbo( IDBDataFile* pFile,
const unsigned char* writeBuf,
const uint64_t fbo,
const int numOfBlock );
int writeDBFileNoVBCache(CommBlock & cb,
DataBlock * block,
const int fbo)
{ return writeDBFileNoVBCache(cb, block->data, fbo); }
/**
* @brief Write a sub block entry directly to a DB file
*/
EXPORT const int writeSubBlockEntry(IDBDataFile* pFile,
DataBlock* block,
const uint64_t lbid,
const int sbid,
const int entryNo,
const int width,
void* pStruct );
EXPORT const int writeSubBlockEntry(CommBlock& cb,
DataBlock* block,
const uint64_t lbid,
const int sbid,
const int entryNo,
const int width,
void* pStruct ) ;
/**
* @brief Write to version buffer
*/
EXPORT const int writeVB( IDBDataFile* pFile,
const OID oid,
const uint64_t lbid );
EXPORT virtual int readDbBlocks( IDBDataFile* pFile,
unsigned char* readBuf,
uint64_t fbo,
size_t n);
EXPORT virtual int restoreBlock( IDBDataFile* pFile,
const unsigned char* writeBuf,
uint64_t fbo);
EXPORT virtual IDBDataFile* getFilePtr(const Column& column,
bool useTmpSuffix);
virtual void chunkManager(ChunkManager* ptr) { m_chunkManager = ptr; }
virtual ChunkManager* chunkManager() { return m_chunkManager; }
protected:
ChunkManager* m_chunkManager;
private:
};
} //end of namespace
#undef EXPORT
#endif // _WE_DBFILEOP_H_

View File

@ -0,0 +1,560 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
* $Id: we_dbrootextenttracker.cpp 4631 2013-05-02 15:21:09Z dcathey $
*/
#include "we_dbrootextenttracker.h"
#include <algorithm>
#include <sstream>
#include "we_brm.h"
#include "we_config.h"
#include "we_log.h"
namespace
{
const char* stateStrings[] = { "initState" ,
"PartialExtent" ,
"EmptyDbRoot" ,
"ExtentBoundary",
"OutOfService" };
}
namespace WriteEngine
{
//------------------------------------------------------------------------------
// DBRootExtentInfo constructor
//------------------------------------------------------------------------------
DBRootExtentInfo::DBRootExtentInfo(
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
BRM::LBID_t startLbid,
HWM localHwm,
uint64_t dbrootTotalBlocks,
DBRootExtentInfoState state) :
fPartition(partition),
fDbRoot(dbRoot),
fSegment(segment),
fStartLbid(startLbid),
fLocalHwm(localHwm),
fDBRootTotalBlocks(dbrootTotalBlocks),
fState(state)
{
}
//------------------------------------------------------------------------------
// LessThan operator used to sort DBRootExtentInfo objects by DBRoot.
//------------------------------------------------------------------------------
bool DBRootExtentInfo::operator<(
const DBRootExtentInfo& entry) const
{
if (fDbRoot < entry.fDbRoot)
return true;
return false;
}
//------------------------------------------------------------------------------
// DBRootExtentTracker constructor
//
// Mutex lock not needed in this function as it is only called from main thread
// before processing threads are spawned.
//------------------------------------------------------------------------------
DBRootExtentTracker::DBRootExtentTracker ( OID oid,
const std::vector<int>& colWidths,
const std::vector<BRM::EmDbRootHWMInfo_v>& dbRootHWMInfoColVec,
unsigned int columnIdx,
Log* logger ) :
fOID(oid),
fLog(logger),
fCurrentDBRootIdx(-1),
fEmptyOrDisabledPM(false),
fEmptyPM(true),
fDisabledHWM(false)
{
const BRM::EmDbRootHWMInfo_v& emDbRootHWMInfo =
dbRootHWMInfoColVec[columnIdx];
int colWidth = colWidths[columnIdx];
fBlksPerExtent = (long long)BRMWrapper::getInstance()->getExtentRows() *
(long long)colWidth / (long long)BYTE_PER_BLOCK;
std::vector<bool> resetState;
for (unsigned int i=0; i<emDbRootHWMInfo.size(); i++)
{
resetState.push_back(false);
DBRootExtentInfoState state = determineState(
colWidths[columnIdx],
emDbRootHWMInfo[i].localHWM,
emDbRootHWMInfo[i].totalBlocks,
emDbRootHWMInfo[i].status);
// For a full extent...
// check to see if any of the column HWMs are partially full, in which
// case we consider all the columns for that DBRoot to be partially
// full. (This can happen if a table has columns with varying widths,
// as the HWM may be at the last extent block for a shorter column, and
// still have free blocks for wider columns.)
if (state == DBROOT_EXTENT_EXTENT_BOUNDARY)
{
for (unsigned int kCol=0; kCol<dbRootHWMInfoColVec.size(); kCol++)
{
const BRM::EmDbRootHWMInfo_v& emDbRootHWMInfo2 =
dbRootHWMInfoColVec[kCol];
DBRootExtentInfoState state2 = determineState(
colWidths[kCol],
emDbRootHWMInfo2[i].localHWM,
emDbRootHWMInfo2[i].totalBlocks,
emDbRootHWMInfo2[i].status);
if (state2 == DBROOT_EXTENT_PARTIAL_EXTENT)
{
state = DBROOT_EXTENT_PARTIAL_EXTENT;
resetState[ resetState.size()-1 ] = true;
break;
}
}
}
DBRootExtentInfo dbRootExtent(
emDbRootHWMInfo[i].dbRoot,
emDbRootHWMInfo[i].partitionNum,
emDbRootHWMInfo[i].segmentNum,
emDbRootHWMInfo[i].startLbid,
emDbRootHWMInfo[i].localHWM,
emDbRootHWMInfo[i].totalBlocks,
state);
fDBRootExtentList.push_back( dbRootExtent );
}
std::sort( fDBRootExtentList.begin(), fDBRootExtentList.end() );
if (fLog)
{
// Always log this info for now; may control with debug later
//if (fLog->isDebug(DEBUG_1))
{
std::ostringstream oss;
oss << "Starting DBRoot info for OID " << fOID;
for (unsigned int k=0; k<fDBRootExtentList.size(); k++)
{
oss << std::endl;
oss << " DBRoot-" << fDBRootExtentList[k].fDbRoot <<
", part/seg/hwm/LBID/totBlks/state: " <<
fDBRootExtentList[k].fPartition <<
"/" << fDBRootExtentList[k].fSegment <<
"/" << fDBRootExtentList[k].fLocalHwm <<
"/" << fDBRootExtentList[k].fStartLbid <<
"/" << fDBRootExtentList[k].fDBRootTotalBlocks <<
"/" << stateStrings[ fDBRootExtentList[k].fState ];
if (resetState[k])
oss << ".";
}
fLog->logMsg( oss.str(), MSGLVL_INFO2 );
}
}
}
//------------------------------------------------------------------------------
// Determines the state of the HWM extent (for a DBRoot); considering the
// current BRM status, HWM, and total block count for the DBRoot.
//------------------------------------------------------------------------------
DBRootExtentInfoState DBRootExtentTracker::determineState(int colWidth,
HWM localHwm,
uint64_t dbRootTotalBlocks,
int16_t status)
{
DBRootExtentInfoState extentState;
if (status == BRM::EXTENTOUTOFSERVICE)
{
extentState = DBROOT_EXTENT_OUT_OF_SERVICE;
}
else
{
if (dbRootTotalBlocks == 0)
{
extentState = DBROOT_EXTENT_EMPTY_DBROOT;
}
else
{
extentState = DBROOT_EXTENT_PARTIAL_EXTENT;
// See if local hwm is on an extent bndry,in which case the extent
// is full and we won't be adding rows to the current HWM extent;
// we will instead need to allocate a new extent in order to begin
// adding any rows.
long long nRows= ((long long)(localHwm+1) *
(long long)BYTE_PER_BLOCK)/ (long long)colWidth;
long long nRem = nRows % BRMWrapper::getInstance()->getExtentRows();
if (nRem == 0)
{
extentState = DBROOT_EXTENT_EXTENT_BOUNDARY;
}
}
}
return extentState;
}
//------------------------------------------------------------------------------
// Select the first segment file to add rows to for the local PM.
// Function will first try to find the HWM extent with the fewest blocks.
// If all the HWM extents are full, then we select the DBRoot/segment file
// with the fewest total overall blocks for that DBRoot.
// Return value is 0 upon success, else non zero if no eligible entries found.
//
// Mutex lock not needed in this function as it is only called from main thread
// before processing threads are spawned.
//------------------------------------------------------------------------------
int DBRootExtentTracker::selectFirstSegFile(
DBRootExtentInfo& dbRootExtent, bool& bNoStartExtentOnThisPM,
bool& bEmptyPM,
std::string& errMsg )
{
int startExtentIdx = -1;
int fewestLocalBlocksIdx = -1; // track HWM extent with fewest blocks
int fewestTotalBlocksIdx = -1; // track DBRoot with fewest total blocks
bNoStartExtentOnThisPM = false;
unsigned int fewestTotalBlks = UINT_MAX;
unsigned int fewestLocalBlks = UINT_MAX;
uint16_t fewestTotalBlkSegNum = USHRT_MAX;
uint16_t fewestLocalBlkSegNum = USHRT_MAX;
// Find DBRoot having HWM extent with fewest blocks. If all HWM extents
// are full (remblks=0), then fall-back on selecting the DBRoot with fewest
// total blks.
//
// Selecting HWM extent with fewest blocks should be straight forward, be-
// cause all the DBRoots on a PM should end on an extent boundary except
// for the current last extent. But if the user has moved a DBRoot, then
// we can end up with 2 partially filled HWM extents on 2 DBRoots, on the
// same PM. That's why we loop through the DBRoots to see if we have more
// than 1 partially filled HWM extent.
for (unsigned int iroot=0;
iroot<fDBRootExtentList.size();
iroot++)
{
// Skip over DBRoots which have no extents
if (fDBRootExtentList[iroot].fState == DBROOT_EXTENT_EMPTY_DBROOT)
continue;
fEmptyPM = false;
// Find DBRoot and segment file with most incomplete extent.
// Break a tie by selecting the lowest segment number.
long long remBlks = (long long)(fDBRootExtentList[iroot].fLocalHwm + 1)%
fBlksPerExtent;
if (remBlks > 0)
{
if ( (remBlks < fewestLocalBlks) ||
((remBlks == fewestLocalBlks) &&
(fDBRootExtentList[iroot].fSegment < fewestLocalBlkSegNum)) )
{
fewestLocalBlocksIdx = iroot;
fewestLocalBlks = remBlks;
fewestLocalBlkSegNum = fDBRootExtentList[iroot].fSegment;
}
}
// Find DBRoot with fewest total of blocks.
// Break a tie by selecting the highest segment number.
if ( (fDBRootExtentList[iroot].fDBRootTotalBlocks < fewestTotalBlks) ||
((fDBRootExtentList[iroot].fDBRootTotalBlocks== fewestTotalBlks) &&
(fDBRootExtentList[iroot].fSegment > fewestTotalBlkSegNum)) )
{
fewestTotalBlocksIdx = iroot;
fewestTotalBlks = fDBRootExtentList[iroot].fDBRootTotalBlocks;
fewestTotalBlkSegNum = fDBRootExtentList[iroot].fSegment;
}
}
// Select HWM extent with fewest number of blocks;
// If chosen extent is disabled, then treat like an empty PM,
// meaning we have to allocate a new extent before adding any rows
if (fewestLocalBlocksIdx != -1)
{
startExtentIdx = fewestLocalBlocksIdx;
if (fDBRootExtentList[startExtentIdx].fState ==
DBROOT_EXTENT_OUT_OF_SERVICE)
{
fDisabledHWM = true;
}
}
// If the HWM on each DBRoot ends on an extent boundary, then
// select the DBRoot with the fewest total number of blocks;
// If chosen extent is disabled, then treat like an empty PM,
// meaning we have to allocate a new extent before adding any rows
else if (fewestTotalBlocksIdx != -1)
{
startExtentIdx = fewestTotalBlocksIdx;
if (fDBRootExtentList[startExtentIdx].fState ==
DBROOT_EXTENT_OUT_OF_SERVICE)
{
fDisabledHWM = true;
}
}
// PM with no extents (or all extents disabled), so select DBRoot/segment
// file from DBRoot list, where we will start inserting rows.
// Select lowest segment file number.
else
{
RETURN_ON_ERROR( selectFirstSegFileForEmptyPM( errMsg ) );
startExtentIdx = fCurrentDBRootIdx;
}
if ((fEmptyOrDisabledPM) || (fDisabledHWM))
bNoStartExtentOnThisPM = true;
bEmptyPM = fEmptyPM;
fCurrentDBRootIdx = startExtentIdx;
// Finish Initializing DBRootExtentList for empty DBRoots w/o any extents
initEmptyDBRoots( );
logFirstDBRootSelection( );
dbRootExtent = fDBRootExtentList[startExtentIdx];
fDBRootExtentList[startExtentIdx].fState = DBROOT_EXTENT_EXTENT_BOUNDARY;
return NO_ERROR;
}
//------------------------------------------------------------------------------
// If we have encountered a PM with no extents (or all extent disabled), then
// this function can be called to determine the DBRoot to be used for the 1st
// extent for the applicable PM. First DBRoot for relevant PM is selected.
// At extent creation time, BRM will assign the segment number.
//
// Mutex lock not needed in this function as it is only called from main thread
// before processing threads are spawned.
//------------------------------------------------------------------------------
int DBRootExtentTracker::selectFirstSegFileForEmptyPM( std::string& errMsg )
{
fEmptyOrDisabledPM = true;
fCurrentDBRootIdx = 0; // Start with first DBRoot for this PM
// Always start empty PM with partition number 0. If the DBRoot has a HWM
// extent that is disabled, then BRM will override this partition number.
fDBRootExtentList[fCurrentDBRootIdx].fPartition = 0;
return NO_ERROR;
}
//------------------------------------------------------------------------------
// Finish Initializing fDBRootExtentList for any empty DBRoots w/o any extents.
//------------------------------------------------------------------------------
void DBRootExtentTracker::initEmptyDBRoots( )
{
int startExtentIdx= fCurrentDBRootIdx;
bool bAnyChanges = false; // If fDBRootExtentList changes, log the contents
// Fill in starting partition for any DBRoots having no extents
for (unsigned int iroot=0;
iroot<fDBRootExtentList.size();
iroot++)
{
if ((fDBRootExtentList[iroot].fState == DBROOT_EXTENT_EMPTY_DBROOT) &&
((int)iroot != startExtentIdx)) // skip over selected dbroot
{
if (fDBRootExtentList[iroot].fPartition !=
fDBRootExtentList[startExtentIdx].fPartition)
{
bAnyChanges = true;
fDBRootExtentList[iroot].fPartition =
fDBRootExtentList[startExtentIdx].fPartition;
}
}
}
// Log fDBRootExtentList if modifications were made
if ((bAnyChanges) && (fLog))
{
// Always log this info for now; may control with debug later
//if (fLog->isDebug(DEBUG_1))
{
std::ostringstream oss;
oss << "Updated starting (empty) DBRoot info for OID " << fOID;
for (unsigned int k=0; k<fDBRootExtentList.size(); k++)
{
oss << std::endl;
oss << " DBRoot-" << fDBRootExtentList[k].fDbRoot <<
", part/seg/hwm/LBID/totBlks/state: " <<
fDBRootExtentList[k].fPartition <<
"/" << fDBRootExtentList[k].fSegment <<
"/" << fDBRootExtentList[k].fLocalHwm <<
"/" << fDBRootExtentList[k].fStartLbid <<
"/" << fDBRootExtentList[k].fDBRootTotalBlocks <<
"/" << stateStrings[ fDBRootExtentList[k].fState ];
}
fLog->logMsg( oss.str(), MSGLVL_INFO2 );
}
}
}
//------------------------------------------------------------------------------
// Assign the DBRoot/segment file to be used for extent loading based on the
// setting in the specified reference tracker (set for a reference column).
//
// Mutex lock not needed in this function as it is only called from main thread
// before processing threads are spawned.
//------------------------------------------------------------------------------
void DBRootExtentTracker::assignFirstSegFile(
const DBRootExtentTracker& refTracker,
DBRootExtentInfo& dbRootExtent)
{
// Start with the same DBRoot index as the reference tracker; assumes that
// DBRoots for each column are listed in same order in fDBRootExtentList.
// That should be a safe assumption since DBRootExtentTracker constructor
// sorts the entries in fDBRootExtentList by fDbRoot.
int startExtentIdx = refTracker.fCurrentDBRootIdx;
fEmptyOrDisabledPM = refTracker.fEmptyOrDisabledPM;
fEmptyPM = refTracker.fEmptyPM;
fDisabledHWM = refTracker.fDisabledHWM;
// Always start empty PM with partition number 0. If the DBRoot has a HWM
// extent that is disabled, then BRM will override this partition number.
if (fEmptyOrDisabledPM)
{
fDBRootExtentList[startExtentIdx].fPartition = 0;
}
fCurrentDBRootIdx = startExtentIdx;
// Finish Initializing DBRootExtentList for empty DBRoots w/o any extents
initEmptyDBRoots( );
logFirstDBRootSelection( );
dbRootExtent = fDBRootExtentList[startExtentIdx];
fDBRootExtentList[startExtentIdx].fState = DBROOT_EXTENT_EXTENT_BOUNDARY;
}
//------------------------------------------------------------------------------
// Log information about the first DBRoot/segment file that is selected.
//------------------------------------------------------------------------------
void DBRootExtentTracker::logFirstDBRootSelection( ) const
{
if (fLog)
{
int extentIdx = fCurrentDBRootIdx;
if (fEmptyOrDisabledPM)
{
std::ostringstream oss;
oss << "No active extents; will add partition to start adding "
"rows for oid-" << fOID <<
"; DBRoot-" << fDBRootExtentList[extentIdx].fDbRoot;
fLog->logMsg( oss.str(), MSGLVL_INFO2 );
}
else if (fDisabledHWM)
{
std::ostringstream oss;
oss << "HWM extent disabled; will add partition to start adding "
"rows for oid-" << fOID <<
"; DBRoot-" << fDBRootExtentList[extentIdx].fDbRoot;
fLog->logMsg( oss.str(), MSGLVL_INFO2 );
}
else
{
std::ostringstream oss;
oss<<"Selecting existing segFile to begin adding rows: oid-"<<fOID<<
"; DBRoot-" << fDBRootExtentList[extentIdx].fDbRoot <<
", part/seg/hwm/LBID/totBlks/state: " <<
fDBRootExtentList[extentIdx].fPartition <<
"/" << fDBRootExtentList[extentIdx].fSegment <<
"/" << fDBRootExtentList[extentIdx].fLocalHwm <<
"/" << fDBRootExtentList[extentIdx].fStartLbid <<
"/" << fDBRootExtentList[extentIdx].fDBRootTotalBlocks<<
"/" << stateStrings[ fDBRootExtentList[extentIdx].fState ];
fLog->logMsg( oss.str(), MSGLVL_INFO2 );
}
}
}
//------------------------------------------------------------------------------
// Iterate/return next DBRoot to be used for the next extent
//
// If it is the "very" 1st extent for the specified DBRoot, then the applicable
// partition to be used for the first extent, is also returned.
// If a partial extent is to be filled in, then the current HWM
// and starting LBID for the relevant extent are returned.
// If a disabled extent is encountered, the return flag is true, so that
// we can allocate a new extent at the next physical partition. BRM should
// take care of figuring out where to allocate this next extent.
//
// Returns true if new extent needs to be allocated, else false indicates that
// the extent is partially full.
//------------------------------------------------------------------------------
bool DBRootExtentTracker::nextSegFile(
uint16_t& dbRoot,
uint32_t& partition,
uint16_t& segment,
HWM& localHwm,
BRM::LBID_t& startLbid)
{
boost::mutex::scoped_lock lock(fDBRootExtTrkMutex);
fCurrentDBRootIdx++;
if ((unsigned int)fCurrentDBRootIdx >= fDBRootExtentList.size())
fCurrentDBRootIdx = 0;
dbRoot = fDBRootExtentList[fCurrentDBRootIdx].fDbRoot;
segment = fDBRootExtentList[fCurrentDBRootIdx].fSegment;
partition = fDBRootExtentList[fCurrentDBRootIdx].fPartition;
localHwm = fDBRootExtentList[fCurrentDBRootIdx].fLocalHwm;
startLbid = fDBRootExtentList[fCurrentDBRootIdx].fStartLbid;
//std::cout << "NextSegFile: Current idx: " << fCurrentDBRootIdx <<
//"; new dbroot: " << dbRoot <<
//"; segment: " << segment <<
//"; partition: " << partition <<
//"; localHwm: " << localHwm <<
//"; startLbid: " << startLbid <<
//"; state: " << stateStrings[fDBRootExtentList[fCurrentDBRootIdx].fState]
// << std::endl;
bool bAllocExtentFlag = true;
if (fDBRootExtentList[fCurrentDBRootIdx].fState ==
DBROOT_EXTENT_PARTIAL_EXTENT)
bAllocExtentFlag = false;
// After we have taken care of the "first" extent for each DBRoot, we can
// zero out everything. The only thing we need to continue rotating thru
// the DBRoots, is the DBRoot number itself.
fDBRootExtentList[fCurrentDBRootIdx].fSegment = 0;
fDBRootExtentList[fCurrentDBRootIdx].fPartition = 0;
fDBRootExtentList[fCurrentDBRootIdx].fLocalHwm = 0;
fDBRootExtentList[fCurrentDBRootIdx].fStartLbid = 0;
fDBRootExtentList[fCurrentDBRootIdx].fDBRootTotalBlocks = 0;
fDBRootExtentList[fCurrentDBRootIdx].fState = DBROOT_EXTENT_EXTENT_BOUNDARY;
return bAllocExtentFlag;
}
const std::vector<DBRootExtentInfo>& DBRootExtentTracker::getDBRootExtentList()
{
boost::mutex::scoped_lock lock(fDBRootExtTrkMutex);
return fDBRootExtentList;
}
} // end of namespace

View File

@ -0,0 +1,240 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
* $Id: we_dbrootextenttracker.h 4631 2013-05-02 15:21:09Z dcathey $
*/
/** @file we_dbrootextenttracker.h
* Contains classes to track the order of placement (rotation) of extents as
* they are filled in and/or added to the DBRoots for the local PM.
*
* DBRootExtentTracker did select the next DBRoot and segment number when-
* ever either selectFirstSegFile() or nextSegFile() were called. The logic
* for selecting a "new" segment file number previously in nextSegFile() has
* been moved to the DBRM extent allocation function. The segment number
* argument returned by nextSegFile() is now only applicable if the return
* value is false, indicating that a partially filled extent has been en-
* countered.
*/
#ifndef WE_DBROOTEXTENTTRACKER_H_
#define WE_DBROOTEXTENTTRACKER_H_
#include <boost/thread/mutex.hpp>
#include <vector>
#include "we_type.h"
#include "brmtypes.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
namespace WriteEngine
{
class Log;
//
// PARTIAL_EXTENT - Extent is partially filled
// EMPTY_DBROOT - DRoot is empty (has no extents)
// EXTENT_BOUNDARY- Encountered extent boundary, add next extent
// OUT_OF_SERVICE - Extent is disabled or out-of-service
//
// Changes to this enum should be reflected in stateStrings array in
// we_dbrootextenttracker.cpp.
//
enum DBRootExtentInfoState
{
DBROOT_EXTENT_PARTIAL_EXTENT = 1,
DBROOT_EXTENT_EMPTY_DBROOT = 2,
DBROOT_EXTENT_EXTENT_BOUNDARY = 3,
DBROOT_EXTENT_OUT_OF_SERVICE = 4
};
//------------------------------------------------------------------------------
/** @brief Tracks the current DBRoot/extent we are loading.
*/
//------------------------------------------------------------------------------
struct DBRootExtentInfo
{
uint32_t fPartition;
uint16_t fDbRoot;
uint16_t fSegment;
BRM::LBID_t fStartLbid;
HWM fLocalHwm;
uint64_t fDBRootTotalBlocks;
DBRootExtentInfoState fState;
DBRootExtentInfo() :
fPartition(0),
fDbRoot(0),
fSegment(0),
fStartLbid(0),
fLocalHwm(0),
fDBRootTotalBlocks(0),
fState(DBROOT_EXTENT_PARTIAL_EXTENT) { }
DBRootExtentInfo(
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
BRM::LBID_t startLbid,
HWM localHwm,
uint64_t dbrootTotalBlocks,
DBRootExtentInfoState state);
bool operator<(const DBRootExtentInfo& entry) const;
};
//------------------------------------------------------------------------------
/** @brief Class to track the order of placement (rotation) of extents as
* they are filled in and/or added to the DBRoots for the relevant PM.
*/
//------------------------------------------------------------------------------
class DBRootExtentTracker
{
public:
/** @brief DBRootExtentTracker constructor
* @param oid Column OID of interest.
* @param colWidths Widths (in bytes) of all the columns in the table.
* @param dbRootHWMInfoColVec Column HWM, DBRoots, etc for this table.
* @param columnIdx Index (into colWidths and dbRootHWMInfoColVec)
* referencing the column that applies to this ExtentTracker.
* @param logger Logger to be used for logging messages.
*/
EXPORT DBRootExtentTracker ( OID oid,
const std::vector<int>& colWidths,
const std::vector<BRM::EmDbRootHWMInfo_v>& dbRootHWMInfoColVec,
unsigned int columnIdx,
Log* logger );
/** @brief Select the first DBRoot/segment file to add rows to, for this PM.
* @param dbRootExtent Dbroot/segment file selected for first set of rows.
* @param bNoStartExtentOnThisPM Is starting HWM extent missing or disabled.
* If HWM extent is missing or disabled, the app will have to allo-
* cate a new extent (at the DBRoot returned in dbRootExtent)) in
* order to add any rows.
* @param bEmptyPM Is this PM void of any available extents
* @return Returns NO_ERROR if success, else returns error code.
*/
EXPORT int selectFirstSegFile ( DBRootExtentInfo& dbRootExtent,
bool& bNoStartExtentOnThisPM,
bool& bEmptyPM,
std::string& errMsg );
/** @brief Set up this Tracker to select the same first DBRoot/segment file
* as the reference DBRootExtentTracker that is specified from a ref column.
*
* Application code should call selectFirstSegFile for a reference column,
* and assignFirstSegFile for all other columns in the same table.
* @param refTracker Tracker object used to assign first DBRoot/segment.
* @param dbRootExtent Dbroot/segment file selected for first set of rows.
*/
EXPORT void assignFirstSegFile( const DBRootExtentTracker& refTracker,
DBRootExtentInfo& dbRootExtent );
/** @brief Iterate/return next DBRoot to be used for the next extent.
*
* Case 1)
* If it is the "very" first extent for the specified DBRoot, then the
* applicable partition to be used for the first extent is also returned.
*
* Case 2)
* If the user moves a DBRoot to a different PM, then the next cpimport.bin
* job on the recepient PM may encounter 2 partially filled in extents.
* This differs from the norm, where we only have 1 partially filled extent
* at any given time, on a PM. When a DBRoot is moved, we may finish an ex-
* tent on 1 DBRoot, and instead of advancing to start a new extent, we ro-
* tate to the recently moved DBRoot, and have to first fill in a partilly
* filled in extent instead of adding a new extent. Case 2 is intended to
* cover this use case.
* In this case, in the middle of an import, if the next extent to receive
* rows is a partially filled in extent, then the DBRoot, partition, and
* segment number for the partial extent are returned. In addition, the
* current HWM and starting LBID for the relevant extent are returned.
*
* Case 3)
* If we are just finishing one extent and adding the next extent, then
* only the DBRoot argument is relevant, telling us where to create the
* next extent. Return value will be true. This case also applies to
* the instance where the HWM extent for the next DBRoot is disabled.
*
* @param dbRoot DBRoot for the next extent
* @param partition If first extent on dbRoot (or partial extent), then
* this is the partition #
* @param segment If partially full extent, then this is the segment #
* @param localHwm If partially full extent, then this is current HWM.
* @param startLbid If partially full extent, then this is starting LBID of
* the current HWM extent.
*
* @return Returns true if new extent needs to be allocated, returns false
* if extent is partially full, and has room for more rows.
*/
EXPORT bool nextSegFile( uint16_t& dbRoot,
uint32_t& partition,
uint16_t& segment,
HWM& localHwm,
BRM::LBID_t& startLbid );
/** @brief get the DBRootExtentInfo list
*/
const std::vector<DBRootExtentInfo>& getDBRootExtentList();
/** @brief get the CurrentDBRootIdx
*/
inline const int getCurrentDBRootIdx()
{
boost::mutex::scoped_lock lock(fDBRootExtTrkMutex);
return fCurrentDBRootIdx;
}
private:
DBRootExtentInfoState determineState(int colWidth,
HWM localHwm,
uint64_t dbRootTotalBlocks,
int16_t status);
// Select First DBRoot/segment file on a PM having no extents for fOID
int selectFirstSegFileForEmptyPM ( std::string& errMsg );
void initEmptyDBRoots(); // init ExtentList for empty DBRoots
void logFirstDBRootSelection() const;
OID fOID; // applicable colunn OID
long long fBlksPerExtent; // blocks per extent for fOID
Log* fLog; // logger
boost::mutex fDBRootExtTrkMutex; // mutex to access fDBRootExtentList
int fCurrentDBRootIdx; // Index into fDBRootExtentList,
// DBRoot where current extent is
// being added
std::vector<DBRootExtentInfo> fDBRootExtentList; // List of current pending
// DBRoot/extents for each DBRoot
// assigned to the local PM.
bool fEmptyOrDisabledPM; // true if PM has no extents or all
// extents are disabled
bool fEmptyPM; // true if PM has no available or
// disabled extents
bool fDisabledHWM; // Did job start with disabled HWM
};
} //end of namespace
#undef EXPORT
#endif // WE_DBROOTEXTENTTRACKER_H_

View File

@ -0,0 +1,298 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_define.cpp 4726 2013-08-07 03:38:36Z bwilkinson $
*
*******************************************************************************/
/** @file" **/
#include <string>
#include "we_define.h"
#include "idberrorinfo.h"
#include "errorids.h"
#include "brmtypes.h"
#include "we_brm.h"
/** Namespace WriteEngine **/
namespace WriteEngine
{
WErrorCodes::WErrorCodes() : fErrorCodes()
{
fErrorCodes[ERR_UNKNOWN] = " a Generic (unknown) error";
fErrorCodes[ERR_INVALID_PARAM] = " due to Invalid parameters";
fErrorCodes[ERR_STRUCT_EMPTY] = " because the Structure is empty";
fErrorCodes[ERR_VALUE_OUTOFRANGE] = " because a Value is out of range";
fErrorCodes[ERR_PARSING] = " a Value is out of range";
fErrorCodes[ERR_NO_MEM] = " out of memory";
fErrorCodes[ERR_DML_LOG_NAME] = " construct DML log filename failed";
fErrorCodes[ERR_OPEN_DML_LOG] = " open DML log file failed";
fErrorCodes[ERR_HDFS_BACKUP] = " DML backup error in HDFS";
// File level error
fErrorCodes[ERR_FILE_CREATE] = " The column file could not be created; it may already exist or be inaccessible.";
fErrorCodes[ERR_FILE_OPEN] = " opening a column file. The file was not found or was inaccessible.";
fErrorCodes[ERR_FILE_DELETE] = " it can not delete the file, because it does not exist or was inaccessible. ";
fErrorCodes[ERR_FILE_EXIST] = " The File already exists. ";
fErrorCodes[ERR_FILE_NOT_EXIST] = " The File does not exist. " ;
fErrorCodes[ERR_FILE_NULL] = " The FILE pointer is null." ;
fErrorCodes[ERR_FILE_WRITE] = " Error writing to a database file. ";
fErrorCodes[ERR_FILE_READ] = " Error reading from a database file. ";
fErrorCodes[ERR_FILE_SEEK] = " Error in positioning file handle. ";
fErrorCodes[ERR_FILE_READ_IMPORT] = " Error reading import source file. ";
fErrorCodes[ERR_DIR_CREATE] = " Error in creating a directory. ";
fErrorCodes[ERR_FILE_NEW_EXTENT_FBO] = " New extent FBO too high for current file. ";
fErrorCodes[ERR_FILE_FBO_NEG] = " Specified file FBO is negative. ";
fErrorCodes[ERR_FILE_TRUNCATE] = " Error truncating db file. ";
fErrorCodes[ERR_FILE_DISK_SPACE] = "Not able to add extent; adding extent "
"would exceed max file system disk usage. ";
fErrorCodes[ERR_FILE_STAT] = " Error getting stats on db file. ";
fErrorCodes[ERR_VB_FILE_NOT_EXIST] = " Version buffer file does not exists.";
fErrorCodes[ERR_FILE_FLUSH] = " Error flushing db file. ";
fErrorCodes[ERR_FILE_GLOBBING] = " Error globbing a file name. ";
// XML level error
fErrorCodes[ERR_XML_FILE] = " An xml file error, usually because the file does not exist";
fErrorCodes[ERR_XML_ROOT_ELEM] = " An xml file Root element error ";
fErrorCodes[ERR_XML_EMPTY] = " An Empty XML file ";
fErrorCodes[ERR_XML_PARSE] = " An XML Parsing error";
// table lock level error
fErrorCodes[ERR_TBLLOCK_LOCK_NOT_FOUND]= "Table is not locked.";
fErrorCodes[ERR_TBLLOCK_GET_LOCK] = "Error getting table lock.";
fErrorCodes[ERR_TBLLOCK_GET_LOCK_LOCKED]="Table locked by another user.";
fErrorCodes[ERR_TBLLOCK_RELEASE_LOCK] = "Error releasing table lock.";
fErrorCodes[ERR_TBLLOCK_CHANGE_STATE] = "Error changing table lock state.";
fErrorCodes[ERR_TBLLOCK_GET_INFO] = "Error getting table lock info.";
fErrorCodes[ERR_TBLLOCK_LOCKID_CONFLICT]="Table LockID for different table than expected.";
// DDL/DML Interface level error
fErrorCodes[ERR_STRUCT_VALUE_NOT_MATCH] = " the number of structs does not match with the number of value sets";
fErrorCodes[ERR_ROWID_VALUE_NOT_MATCH] = " the number of rowids does not match with the number of values";
fErrorCodes[ERR_TBL_SYSCAT_ERROR] = "Error occured when querying systemcatalog.";
// index error
fErrorCodes[ERR_IDX_TREE_MOVE_ENTRY] = " an error in moving part of an index tree to a new subblock";
fErrorCodes[ERR_IDX_TREE_INVALID_TYPE] = " an Invalid index tree entry type";
fErrorCodes[ERR_IDX_TREE_BITTEST_VAL] = " a Wrong bit test value in the index tree entry";
fErrorCodes[ERR_IDX_TREE_INVALID_LEVEL] = " an Invalid testbit index tree level";
fErrorCodes[ERR_IDX_TREE_INVALID_GRP] = "an Invalid index tree group type ";
fErrorCodes[ERR_IDX_TREE_LISTPTR_CHANGE] = " an index tree List pointer change";
//index list error
fErrorCodes[ERR_IDX_LIST_INVALID_ADDHDR] = " a Create indexlist header error";
fErrorCodes[ERR_IDX_LIST_INVALID_UPDATE] = " an pdate Index List error ";
fErrorCodes[ERR_IDX_LIST_INVALID_DELETE] = " a Delete rowid in indexlist err";
fErrorCodes[ERR_IDX_LIST_INVALID_KEY] = " an Invalid index listbppseeder.cpp Key passed";
fErrorCodes[ERR_IDX_LIST_GET_RID_ARRARY] = " an index list RID array";
fErrorCodes[ERR_IDX_LIST_WRONG_KEY ] = " a not matched Key passed to an index list";
fErrorCodes[ERR_IDX_LIST_HDR_EMPTY] = " an empty index list header";
fErrorCodes[ERR_IDX_LIST_GET_SEGMT] = " in an index list Get Segment";
fErrorCodes[ERR_IDX_LIST_WRONG_LBID_WRITE] = " an index list incorrect LBID write";
fErrorCodes[ERR_IDX_LIST_UPDATE_SUB] = " in an index list update sub";
fErrorCodes[ERR_IDX_LIST_UPDATE_NARRAY] = " in an index list update narray";
fErrorCodes[ERR_IDX_LIST_LAST_FBO_NEG] = " the last index list FBO neg";
fErrorCodes[ERR_IDX_LIST_INIT_NEW_BLKS] = " in an index list initialize new blocks";
fErrorCodes[ERR_IDX_LIST_INIT_LINK_BLKS] = " in an index list initialize link blocks";
fErrorCodes[ERR_IDX_LIST_UPDATE_COUNT] = " in an index list update count";
fErrorCodes[ERR_IDX_LIST_SET_NEXT_LBID] = " in an index list set next LBID";
fErrorCodes[ERR_IDX_LIST_INVALID_LBID] = "an index list invalid LBID";
fErrorCodes[ERR_IDX_LIST_INVALID_BLK_READ] = " in an index list invalid LBID read";
fErrorCodes[ERR_IDX_LIST_UPDATE_HDR_COUNT] = " in an index list update header count";
fErrorCodes[ERR_IDX_LIST_WRONG_BLK] = " an index list wrong block";
fErrorCodes[ERR_IDX_LIST_WRONG_TYPE] = " an index list wrong type";
fErrorCodes[ERR_IDX_LIST_GET_COUNT] = " in an index list get count";
fErrorCodes[ERR_IDX_LIST_GET_NEXT] = " in an index list get next";
fErrorCodes[ERR_IDX_LIST_GET_PARENT] = " in an index list get parent";
fErrorCodes[ERR_IDX_LIST_GET_SUB_BLK] = " in an index list get sub block";
fErrorCodes[ERR_IDX_LIST_INVALID_UP_HDR] = " an invalid Update Index List header ";
fErrorCodes[ERR_IDX_LIST_INVALID_ADD_LIST] = " an invalid add Index List";
fErrorCodes[ERR_IDX_LIST_INVALID_UP] = " an invalid Update Index List";
//freemgr error
fErrorCodes[ERR_FM_ASSIGN_ERR] = " in an assignment";
fErrorCodes[ERR_FM_RELEASE_ERR] = " in a release";
fErrorCodes[ERR_FM_BAD_FBO] = " an invalid File Block Offset";
fErrorCodes[ERR_FM_BAD_TYPE] = "an invalid type that must be pointer or list";
fErrorCodes[ERR_FM_NO_SPACE] = " that No blocks are available";
fErrorCodes[ERR_FM_EXTEND] = " while extending a file";
// Dictionary error
fErrorCodes[ERR_DICT_NO_SPACE_INSERT] = " no space for a dictionary insert";
fErrorCodes[ERR_DICT_SIZE_GT_8000] = " the dictionary size was >8000";
fErrorCodes[ERR_DICT_NO_OP_DELETE] = " in the dictionary no op delete";
fErrorCodes[ERR_DICT_NO_OFFSET_DELETE] = " a dictionary bad Delete offset";
fErrorCodes[ERR_DICT_INVALID_HDR] = " a dictionary bad Delete Hdr";
fErrorCodes[ERR_DICT_ZERO_LEN] = " a dictionary zero len";
fErrorCodes[ERR_DICT_TOKEN_NOT_FOUND] = " a dictionary token not found";
fErrorCodes[ERR_DICT_FILE_NOT_FOUND] = " a dictionary file not found";
fErrorCodes[ERR_DICT_BAD_TOKEN_LBID] = " a dictionary token lbid is bad";
fErrorCodes[ERR_DICT_BAD_TOKEN_OP] = " a dictionary token op is bad";
// Bulk error
fErrorCodes[ERR_BULK_MAX_ERR_NUM] = " the Maximum number of error rows reached";
fErrorCodes[ERR_BULK_DATA_COL_NUM] = " the total number of data column not match with column definitions";
fErrorCodes[ERR_BULK_SEND_MSG_ERR] = " in a bulk load send msg";
fErrorCodes[ERR_BULK_MISSING_EXTENT_ENTRY] = " missing Extent Entry when trying to save LBID info for CP";
fErrorCodes[ERR_BULK_MISSING_EXTENT_ROW] = " missing Extent Row when trying to save LBID info for CP";
fErrorCodes[ERR_BULK_ROW_FILL_BUFFER] = " Single row fills read buffer; try larger read buffer.";
fErrorCodes[ERR_BULK_DBROOT_CHANGE] = " Local PM DBRoot settings changed during bulk load.";
fErrorCodes[ERR_BULK_ROLLBACK_MISS_ROOT] = " Mode3 automatic rollback not performed. DBRoot missing.";
fErrorCodes[ERR_BULK_ROLLBACK_SEG_LIST] = " Error building segment file list in a directory.";
fErrorCodes[ERR_BULK_BINARY_PARTIAL_REC] = " Binary import did not end on fixed length record boundary.";
fErrorCodes[ERR_BULK_BINARY_IGNORE_FLD] = " <IgnoreField> tag not supported for binary imports.";
// BRM error
fErrorCodes[ERR_BRM_LOOKUP_LBID] = " a BRM Lookup LBID error.";
fErrorCodes[ERR_BRM_LOOKUP_FBO] = " a BRM Lookup FBO error.";
fErrorCodes[ERR_BRM_ALLOC_EXTEND] = " a BRM Allocate extent error.";
fErrorCodes[ERR_BRM_COMMIT] = " a BRM Commit error.";
fErrorCodes[ERR_BRM_ROLLBACK] = " a BRM Rollback error.";
fErrorCodes[ERR_BRM_GET_UNCOMM_LBID] = " a BRM get uncommitted lbid list error.";
fErrorCodes[ERR_BRM_DEL_OID] = " a BRM Delete oid error.";
fErrorCodes[ERR_BRM_BEGIN_COPY] = " a BRM Begin copy error.";
fErrorCodes[ERR_BRM_END_COPY] = " a BRM End copy error.";
fErrorCodes[ERR_BRM_GET_HWM] = " a BRM get hwm error.";
fErrorCodes[ERR_BRM_SET_HWM] = " a BRM Set hwm error.";
fErrorCodes[ERR_BRM_WR_VB_ENTRY] = " a BRM VB entry error.";
fErrorCodes[ERR_BRM_VB_COPY_READ] = " a BRM VB copy read error.";
fErrorCodes[ERR_BRM_VB_COPY_SEEK_DB] = " a BRM VB copy seek error against DB file.";
fErrorCodes[ERR_BRM_VB_COPY_SEEK_VB] = " a BRM VB copy seek error against VB file.";
fErrorCodes[ERR_BRM_VB_COPY_WRITE] = " a BRM VB copy write.";
fErrorCodes[ERR_BRM_DEAD_LOCK] = " a BRM DEAD lock error.";
fErrorCodes[ERR_BRM_MARK_INVALID] = " a BRM Mark extent invalid error from casual paritioning.";
fErrorCodes[ERR_BRM_SAVE_STATE] = " a BRM Save state error.";
fErrorCodes[ERR_BRM_GET_START_EXTENT] = " a BRM get start Extent error.";
fErrorCodes[ERR_BRM_VB_OVERFLOW] = "BRM block version buffer overflow error.";
fErrorCodes[ERR_BRM_READ_ONLY] = "BRM is in read-only state.";
fErrorCodes[ERR_BRM_GET_READ_WRITE] = "BRM error getting read-write state.";
fErrorCodes[ERR_BRM_BULK_RB_COLUMN] = "BRM error performing bulk rollback of column extents.";
fErrorCodes[ERR_BRM_BULK_RB_DCTNRY] = "BRM error performing bulk rollback of dictionary store extents.";
fErrorCodes[ERR_BRM_DELETE_EXTENT_COLUMN] = "BRM error deleting column extents.";
fErrorCodes[ERR_BRM_DELETE_EXTENT_DCTNRY] = "BRM error deleting dictionary extents.";
fErrorCodes[ERR_BRM_TAKE_SNAPSHOT] = "BRM error requesting snapshot of BRM state.";
fErrorCodes[ERR_BRM_LOOKUP_START_LBID] = "BRM start LBID lookup error.";
fErrorCodes[ERR_BRM_BULK_UPDATE] = "BRM error executing bulk update of HWM and CP.";
fErrorCodes[ERR_BRM_GET_EXT_STATE] = "BRM error getting segment file extent state.";
fErrorCodes[ERR_EXTENTMAP_LOOKUP] = " a extent map Lookup error.";
fErrorCodes[ERR_BRM_LOOKUP_VERSION] = " a vssLookup version info error.";
fErrorCodes[ERR_BRM_LOOKUP_LBID_RANGES] = " BRM error getting LBID ranges.";
fErrorCodes[ERR_BRM_HWMS_NOT_EQUAL] = " HWMs for same width columns not equal. ";
fErrorCodes[ERR_BRM_HWMS_OUT_OF_SYNC] = " HWMs for different width columns not in sync. ";
fErrorCodes[ERR_BRM_DBROOT_HWMS] = " BRM error getting HWMs for DBRoots. ";
fErrorCodes[ERR_BRM_NETWORK] = " Network error in DBRM call. ";
fErrorCodes[ERR_BRM_READONLY] = " DBRM is read only. ";
fErrorCodes[ERR_INVALID_VBOID] = " The VB oid is invalid ";
fErrorCodes[ERR_BRM_SET_EXTENTS_CP] = " BRM error setting extents min/max ";
fErrorCodes[ERR_BRM_SHUTDOWN] = " The system is being shutdown ";
fErrorCodes[ERR_BRM_GET_SHUTDOWN] = " BRM error get the system shutdown flag ";
fErrorCodes[ERR_BRM_SUSPEND] = " The system is in write suspended mode";
fErrorCodes[ERR_BRM_GET_SUSPEND] = " BRM error get the system suspend flag ";
fErrorCodes[ERR_BRM_BAD_STRIPE_CNT] = " Incorrect number of column extents allocated in stripe";
// DM error
fErrorCodes[ERR_DM_CONVERT_OID] = " a DM Conversion error";
// Cache error
fErrorCodes[ERR_CACHE_KEY_EXIST ] = " a Cache key exists";
fErrorCodes[ERR_CACHE_KEY_NOT_EXIST] = " a Cache key does not exist";
fErrorCodes[ERR_NULL_BLOCK] = " a Block is NULL";
fErrorCodes[ERR_FREE_LIST_EMPTY] = " a Free list is empty";
// Compression error
fErrorCodes[ERR_COMP_COMPRESS] = " Error in compressing data. ";
fErrorCodes[ERR_COMP_UNCOMPRESS] = " Error in uncompressing data. ";
fErrorCodes[ERR_COMP_PARSE_HDRS] = " Error parsing compression headers. ";
fErrorCodes[ERR_COMP_VERIFY_HDRS] = " Error verifying compression headers. ";
fErrorCodes[ERR_COMP_PAD_DATA] = " Error in padding compressed data. ";
fErrorCodes[ERR_COMP_READ_BLOCK] = " Error in reading a data block. ";
fErrorCodes[ERR_COMP_SAVE_BLOCK] = " Error in saving a data block. ";
fErrorCodes[ERR_COMP_WRONG_PTR] = " Invalid pointer in compression headers. ";
fErrorCodes[ERR_COMP_FILE_NOT_FOUND] = " Error searching for a compressed file. ";
fErrorCodes[ERR_COMP_CHUNK_NOT_FOUND] = " Error searching for a compressed chunk. ";
fErrorCodes[ERR_COMP_UNAVAIL_TYPE] = " Unavailable compressino type. ";
fErrorCodes[ERR_COMP_REMOVE_FILE] = " Failed to remove a file. ";
fErrorCodes[ERR_COMP_RENAME_FILE] = " Failed to rename a file. ";
fErrorCodes[ERR_COMP_OPEN_FILE] = " Failed to open a compressed data file. ";
fErrorCodes[ERR_COMP_SET_OFFSET] = " Failed to set offset in a compressed data file. ";
fErrorCodes[ERR_COMP_READ_FILE] = " Failed to read from a compressed data file. ";
fErrorCodes[ERR_COMP_WRITE_FILE] = " Failed to write to a compresssed data file. ";
fErrorCodes[ERR_COMP_CLOSE_FILE] = " Failed to close a compressed data file. ";
fErrorCodes[ERR_COMP_TRUNCATE_ZERO] = " Attempting to truncate compressed file to 0 bytes. ";
// Auto-increment error
fErrorCodes[ERR_AUTOINC_GEN_EXCEED_MAX] = " Generated auto-increment value "
"exceeds maximum value for the column type.";
fErrorCodes[ERR_AUTOINC_USER_OUT_OF_RANGE] = " User specified auto-"
"increment value is out of range for the column type.";
fErrorCodes[ERR_AUTOINC_TABLE_NAME] = " Invalid schema/tablename for auto increment. ";
fErrorCodes[ERR_AUTOINC_INIT1] = " Unable to initialize auto-increment value. ";
fErrorCodes[ERR_AUTOINC_INIT2] = " Unable to initialize auto-increment value. Unknown exception. ";
fErrorCodes[ERR_AUTOINC_RID] = " Failed to get row information from calpontsystemcatalog.";
fErrorCodes[ERR_AUTOINC_START_SEQ] = " Unable to setup AI sequence in BRM.";
fErrorCodes[ERR_AUTOINC_GET_RANGE] = " Unable to reserve AI range from BRM.";
fErrorCodes[ERR_AUTOINC_GET_LOCK] = " Unable to lock AI column in BRM.";
fErrorCodes[ERR_AUTOINC_REL_LOCK] = " Unable to release AI column in BRM.";
fErrorCodes[ERR_AUTOINC_UPDATE] = " Unable to update nextValue in system catalog.";
// Block cache flush error
fErrorCodes[ERR_BLKCACHE_FLUSH_LIST] = " Failed to flush list of blocks from PrimProc cache. ";
// Backup bulk meta data file error
fErrorCodes[ERR_METADATABKUP_FILE_RENAME] = " Unable to rename temporary bulk meta data file. ";
fErrorCodes[ERR_METADATABKUP_COMP_PARSE_HDRS] = " Error parsing compression headers in bulk backup file. ";
fErrorCodes[ERR_METADATABKUP_COMP_VERIFY_HDRS] = " Error verifying compression headers in bulk backup file. ";
fErrorCodes[ERR_METADATABKUP_COMP_CHUNK_NOT_FOUND]= " Error searching for compressed chunk in db file being backed up. ";
fErrorCodes[ERR_METADATABKUP_COMP_OPEN_BULK_BKUP] = " Error opening compressed chunk in bulk backup file. ";
fErrorCodes[ERR_METADATABKUP_COMP_WRITE_BULK_BKUP]= " Error writing compressed chunk to bulk backup file. ";
fErrorCodes[ERR_METADATABKUP_COMP_READ_BULK_BKUP] = " Error reading compressed chunk from bulk backup file. ";
fErrorCodes[ERR_METADATABKUP_COMP_RENAME] = " Unable to rename compressed chunk bulk backup file. ";
}
std::string WErrorCodes::errorString(int code)
{
// Look for error message overrides from system-wide error messages
switch (code)
{
case ERR_FILE_DISK_SPACE:
{
logging::Message::Args args;
std::string msgArg; // empty str arg; no extra info in this context
args.add( msgArg );
return logging::IDBErrorInfo::instance()->errorMsg(
logging::ERR_EXTENT_DISK_SPACE, args);
break;
}
}
int brmRc = BRMWrapper::getBrmRc();
if (brmRc == BRM::ERR_OK)
return (fErrorCodes[code]);
std::string errMsg( fErrorCodes[code] );
std::string brmMsg;
errMsg += " [BRM error status: ";
BRM::errString(brmRc, brmMsg);
errMsg += brmMsg;
errMsg += "]";
return errMsg;
}
} //end of namespace

View File

@ -0,0 +1,393 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id: we_define.h 4726 2013-08-07 03:38:36Z bwilkinson $
/** @file */
#undef NO_ERROR
#ifndef _WE_DEFINE_H_
#define _WE_DEFINE_H_
#include <string>
#include <map>
#include <stdint.h>
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
const short MAX_COLUMN_BOUNDARY = 8; // Max bytes for one column
const int MAX_SIGNATURE_SIZE = 8000; // Max len of dict sig val
const int MAX_FIELD_SIZE = 1000; // Max len non-dict fld val
const int MAX_DB_DIR_LEVEL = 6; // Max lvl of db dir struct
const int MAX_DB_DIR_NAME_SIZE = 20; // Max len of db dir size
const short ROW_PER_BYTE = 8; // Rows/byte in bitmap file
const int BYTE_PER_BLOCK = 8192; // Num bytes per data block
const int BYTE_PER_SUBBLOCK = 256; // Num bytes per sub block
const int ENTRY_PER_SUBBLOCK = 32; // Num entries per sub block
const int INITIAL_EXTENT_ROWS_TO_DISK = 256 * 1024;
// Num rows reserved to disk for 'initial' extent
const int FILE_NAME_SIZE = 200; // Max size of file name
const long long MAX_ALLOW_ERROR_COUNT = 100000; //Max allowable error count
//--------------------------------------------------------------------------
// Dictionary related constants
//--------------------------------------------------------------------------
const uint16_t DCTNRY_END_HEADER = 0xffff ; // end of header
const uint64_t NOT_USED_PTR = 0x0 ; // not continuous ptr
const int HDR_UNIT_SIZE = 2; // hdr unit size
const int NEXT_PTR_BYTES = 8; // const ptr size
const int MAX_OP_COUNT = 1024; // op max size
const int DCTNRY_HEADER_SIZE = 14; // header total size
const int MAX_STRING_CACHE_SIZE = 1000;
// End of Dictionary related constants
const int COLPOSPAIR_NULL_TOKEN_OFFSET= -1; // offset value denoting a null token
const uint32_t BULK_SYSCAT_SESSION_ID = 0; // SessionID for syscat queries
const char COL_TYPE_DICT = 'D'; // Dictionary type
const uint64_t INVALID_LBID = 0xFFFFFFFFFULL; // 2**36 - 1
const unsigned int SUBSYSTEM_ID_DDLPROC = 15;
const unsigned int SUBSYSTEM_ID_DMLPROC = 20;
const unsigned int SUBSYSTEM_ID_WE = 19;
const unsigned int SUBSYSTEM_ID_WE_SRV = 32;
const unsigned int SUBSYSTEM_ID_WE_SPLIT= 33;
const unsigned int SUBSYSTEM_ID_WE_BULK = 34;
//--------------------------------------------------------------------------
// Default definitions
//--------------------------------------------------------------------------
const int DEFAULT_CACHE_BLOCK = 256; // Max num of cache blocks
const int DEFAULT_CHK_INTERVAL = 3; // Checkpoint in seconds
const int DEFAULT_CACHE_PCT_FREE = 25; // Min % of free cache
const int DEFAULT_BUFSIZ = 1*1024*1024; // setvbuf buffer size
const int DEFAULT_COLSIZ = 8; // col size for hdfs rdwr buf
const int BLK_INIT = 0;
const int BLK_READ = 1;
const int BLK_WRITE = 2;
//--------------------------------------------------------------------------
// Return code definitions
//--------------------------------------------------------------------------
const int NO_ERROR = 0; // No error
const int NOT_FOUND = -1; // Not found
const int INVALID_NUM = -1; // Invalid number
//--------------------------------------------------------------------------
// Error code definition
//--------------------------------------------------------------------------
const int ERR_CODEBASE = 1000; // Generic error codes
const int ERR_FILEBASE = 1050; // File-related error codes
const int ERR_XMLBASE = 1150; // XML job file error codes
const int ERR_TBLLOCKBASE = 1200; // Table-lock error codes
const int ERR_WRAPPERBASE = 1250; // DDL/DML API related errors
const int ERR_INDEXBASE = 1300; // Index-related error codes
const int ERR_FMGRBASE = 1350; // Freemgr errors
const int ERR_DCTNRYBASE = 1400; // Dictionary errors
const int ERR_BULKBASE = 1450; // Bulk specific errors
const int ERR_BRMBASE = 1500; // BRM errors
const int ERR_DMBASE = 1550; // Disk manager errors
const int ERR_CACHEBASE = 1600; // Cche management errors
const int ERR_COMPBASE = 1650; // Compression errors
const int ERR_AUTOINCBASE = 1700; // Auto-increment errors
const int ERR_BLKCACHEBASE = 1750; // Block cache flush errors
const int ERR_METABKUPBASE = 1800; // Backup bulk meta file errors
//--------------------------------------------------------------------------
// Generic error
//--------------------------------------------------------------------------
const int ERR_UNKNOWN = ERR_CODEBASE + 1; // Generic error
const int ERR_INVALID_PARAM = ERR_CODEBASE + 2; // Invalid parms
const int ERR_STRUCT_EMPTY = ERR_CODEBASE + 3; // Struct is empty
const int ERR_VALUE_OUTOFRANGE = ERR_CODEBASE + 4; // Val out of range
const int ERR_PARSING = ERR_CODEBASE + 5; // Parsing error
const int ERR_NO_MEM = ERR_CODEBASE + 6; // Mem alloc error
const int ERR_DML_LOG_NAME = ERR_CODEBASE + 7; // DML log filename error
const int ERR_OPEN_DML_LOG = ERR_CODEBASE + 8; // Open DML log file error
const int ERR_HDFS_BACKUP = ERR_CODEBASE + 9; // HDFS backup error
//--------------------------------------------------------------------------
// File level error
//--------------------------------------------------------------------------
const int ERR_FILE_CREATE = ERR_FILEBASE + 1; // File creation error, mostly because file has already existed
const int ERR_FILE_OPEN = ERR_FILEBASE + 2; // Can not open the file, mostly because file not found
const int ERR_FILE_DELETE = ERR_FILEBASE + 3; // Can not delete the file, common reason is file not exist
const int ERR_FILE_EXIST = ERR_FILEBASE + 4; // File alreay exists
const int ERR_FILE_NOT_EXIST = ERR_FILEBASE + 5; // File not exists
const int ERR_FILE_NULL = ERR_FILEBASE + 6; // File is empty
const int ERR_FILE_WRITE = ERR_FILEBASE + 7; // Error writing to a DB file
const int ERR_FILE_READ = ERR_FILEBASE + 8; // Error reading from a DB file
const int ERR_FILE_SEEK = ERR_FILEBASE + 9; // Error in positioning file handle
const int ERR_FILE_READ_IMPORT = ERR_FILEBASE + 10;// Error reading import source file
const int ERR_DIR_CREATE = ERR_FILEBASE + 11;// Error in creating directory
const int ERR_FILE_NEW_EXTENT_FBO = ERR_FILEBASE + 12;// New extent fbo too large
const int ERR_FILE_FBO_NEG = ERR_FILEBASE + 13;// File FBO is negative
const int ERR_FILE_TRUNCATE = ERR_FILEBASE + 14;// Error truncating file
const int ERR_FILE_DISK_SPACE = ERR_FILEBASE + 15;// Out of space on file system
const int ERR_FILE_STAT = ERR_FILEBASE + 16;// Error getting stats on file
const int ERR_VB_FILE_NOT_EXIST = ERR_FILEBASE + 17;// Version buffer file not exists
const int ERR_FILE_FLUSH = ERR_FILEBASE + 18;// Error flushing file
const int ERR_FILE_GLOBBING = ERR_FILEBASE + 19;// Error globbing a file name
//--------------------------------------------------------------------------
// XML level error
//--------------------------------------------------------------------------
const int ERR_XML_FILE = ERR_XMLBASE + 1; // File error, probably because file does not exist
const int ERR_XML_ROOT_ELEM = ERR_XMLBASE + 2; // Root element err
const int ERR_XML_EMPTY = ERR_XMLBASE + 3; // Empty XML file
const int ERR_XML_PARSE = ERR_XMLBASE + 4; // Parsing error
//--------------------------------------------------------------------------
// table lock level error
//--------------------------------------------------------------------------
const int ERR_TBLLOCK_LOCK_NOT_FOUND = ERR_TBLLOCKBASE + 1; // table has no lock
const int ERR_TBLLOCK_GET_LOCK = ERR_TBLLOCKBASE + 2; // error acquiring a table lock
const int ERR_TBLLOCK_GET_LOCK_LOCKED= ERR_TBLLOCKBASE + 3; // table currently locked
const int ERR_TBLLOCK_RELEASE_LOCK = ERR_TBLLOCKBASE + 4; // error releasing a table lock
const int ERR_TBLLOCK_CHANGE_STATE = ERR_TBLLOCKBASE + 5; // error changing state of lock
const int ERR_TBLLOCK_GET_INFO = ERR_TBLLOCKBASE + 6; // error getting info about a lock
const int ERR_TBLLOCK_LOCKID_CONFLICT= ERR_TBLLOCKBASE + 7; // lockID for different table than expected
//--------------------------------------------------------------------------
// DDL/DML Interface level error
//--------------------------------------------------------------------------
const int ERR_STRUCT_VALUE_NOT_MATCH = ERR_WRAPPERBASE + 1; // The number of struct not match with the number of value set
const int ERR_ROWID_VALUE_NOT_MATCH = ERR_WRAPPERBASE + 2; // The number of rowid not match with the number of values
const int ERR_TBL_SYSCAT_ERROR = ERR_WRAPPERBASE + 3; /** @brief Syscatalog query error */
//--------------------------------------------------------------------------
// index error
//--------------------------------------------------------------------------
const int ERR_IDX_TREE_MOVE_ENTRY = ERR_INDEXBASE + 1; // The error in move part of tree to a new subblock
const int ERR_IDX_TREE_INVALID_TYPE = ERR_INDEXBASE + 2; // Invalid tree entry type
const int ERR_IDX_TREE_BITTEST_VAL = ERR_INDEXBASE + 3; // Wrong bit test value in the entry
const int ERR_IDX_TREE_INVALID_LEVEL = ERR_INDEXBASE + 4; // Invalid testbit treel level
const int ERR_IDX_TREE_INVALID_GRP = ERR_INDEXBASE + 5; // Invalid group type
const int ERR_IDX_TREE_LISTPTR_CHANGE = ERR_INDEXBASE + 6; // List pointer change
//index list error
const int ERR_IDX_LIST_INVALID_ADDHDR = ERR_INDEXBASE + 7; // Create indexlist header error
const int ERR_IDX_LIST_INVALID_UPDATE = ERR_INDEXBASE + 8; // Update Index List error
const int ERR_IDX_LIST_INVALID_DELETE = ERR_INDEXBASE + 9; // Delete rowid in indexlist err*/
const int ERR_IDX_LIST_INVALID_KEY = ERR_INDEXBASE + 10;// Invalid Key passed
const int ERR_IDX_LIST_GET_RID_ARRARY = ERR_INDEXBASE + 11;// RID array
const int ERR_IDX_LIST_WRONG_KEY = ERR_INDEXBASE + 12;// not matched Key passed
const int ERR_IDX_LIST_HDR_EMPTY = ERR_INDEXBASE + 13;// Delete rowid in indexlist err
const int ERR_IDX_LIST_GET_SEGMT = ERR_INDEXBASE + 14;// Get Segment
const int ERR_IDX_LIST_WRONG_LBID_WRITE=ERR_INDEXBASE + 15;
const int ERR_IDX_LIST_UPDATE_SUB = ERR_INDEXBASE + 16;
const int ERR_IDX_LIST_UPDATE_NARRAY = ERR_INDEXBASE + 17;
const int ERR_IDX_LIST_LAST_FBO_NEG = ERR_INDEXBASE + 18;
const int ERR_IDX_LIST_INIT_NEW_BLKS = ERR_INDEXBASE + 19;
const int ERR_IDX_LIST_INIT_LINK_BLKS = ERR_INDEXBASE + 20;
const int ERR_IDX_LIST_UPDATE_COUNT = ERR_INDEXBASE + 21;
const int ERR_IDX_LIST_SET_NEXT_LBID = ERR_INDEXBASE + 22;
const int ERR_IDX_LIST_INVALID_LBID = ERR_INDEXBASE + 23;
const int ERR_IDX_LIST_INVALID_BLK_READ=ERR_INDEXBASE + 24;
const int ERR_IDX_LIST_UPDATE_HDR_COUNT=ERR_INDEXBASE + 25;
const int ERR_IDX_LIST_WRONG_BLK = ERR_INDEXBASE + 26;
const int ERR_IDX_LIST_WRONG_TYPE = ERR_INDEXBASE + 27;
const int ERR_IDX_LIST_GET_COUNT = ERR_INDEXBASE + 28;
const int ERR_IDX_LIST_GET_NEXT = ERR_INDEXBASE + 29;
const int ERR_IDX_LIST_GET_PARENT = ERR_INDEXBASE + 30;
const int ERR_IDX_LIST_GET_SUB_BLK = ERR_INDEXBASE + 31;
const int ERR_IDX_LIST_INVALID_UP_HDR = ERR_INDEXBASE + 32;// Update Index List error
const int ERR_IDX_LIST_INVALID_ADD_LIST=ERR_INDEXBASE + 33;// Update Index List error
const int ERR_IDX_LIST_INVALID_UP = ERR_INDEXBASE + 34;// Update Index List error
//--------------------------------------------------------------------------
// freemgr error
//--------------------------------------------------------------------------
const int ERR_FM_ASSIGN_ERR = ERR_FMGRBASE + 1; // General assignment error
const int ERR_FM_RELEASE_ERR = ERR_FMGRBASE + 2; // General release error
const int ERR_FM_BAD_FBO = ERR_FMGRBASE + 3; // File Block Offset err
const int ERR_FM_BAD_TYPE = ERR_FMGRBASE + 4; // type must be pointer or list
const int ERR_FM_NO_SPACE = ERR_FMGRBASE + 5; // No blocks available
const int ERR_FM_EXTEND = ERR_FMGRBASE + 6; // Error extending file
//--------------------------------------------------------------------------
// Dictionary error
//--------------------------------------------------------------------------
const int ERR_DICT_NO_SPACE_INSERT= ERR_DCTNRYBASE+ 1; // ins no space
const int ERR_DICT_SIZE_GT_8000 = ERR_DCTNRYBASE+ 2; // ins size >8000
const int ERR_DICT_NO_OP_DELETE = ERR_DCTNRYBASE+ 3; // del no op
const int ERR_DICT_NO_OFFSET_DELETE=ERR_DCTNRYBASE+ 4; // del bad offset
const int ERR_DICT_INVALID_HDR = ERR_DCTNRYBASE+ 5; // Delete Hdr
const int ERR_DICT_ZERO_LEN = ERR_DCTNRYBASE+ 6; // Delete zero len
const int ERR_DICT_TOKEN_NOT_FOUND= ERR_DCTNRYBASE+ 7; // token not found
const int ERR_DICT_FILE_NOT_FOUND = ERR_DCTNRYBASE+ 8; // dict file not found
const int ERR_DICT_BAD_TOKEN_LBID = ERR_DCTNRYBASE+ 9; // bad token lbid
const int ERR_DICT_BAD_TOKEN_OP = ERR_DCTNRYBASE+ 10;// token op is bad
//--------------------------------------------------------------------------
// Bulk error
//--------------------------------------------------------------------------
const int ERR_BULK_MAX_ERR_NUM = ERR_BULKBASE + 1; // Maximum number of error rows reached
const int ERR_BULK_DATA_COL_NUM = ERR_BULKBASE + 2; // The total number of data column not match with column definitions
const int ERR_BULK_SEND_MSG_ERR = ERR_BULKBASE + 3; // send msg to primproc to flush cache
const int ERR_BULK_MISSING_EXTENT_ENTRY=ERR_BULKBASE + 4; // Missing Extent Entry when trying to save LBID info
const int ERR_BULK_MISSING_EXTENT_ROW = ERR_BULKBASE + 5; // Missing Extent Row when trying to save LBID info
const int ERR_BULK_ROW_FILL_BUFFER = ERR_BULKBASE + 6; // Single row fills read buffer
const int ERR_BULK_DBROOT_CHANGE = ERR_BULKBASE + 7; // Local DBRoot settings changed during an import
const int ERR_BULK_ROLLBACK_MISS_ROOT = ERR_BULKBASE + 8; // Mode3 automatic rollback skipped with missing DBRoot
const int ERR_BULK_ROLLBACK_SEG_LIST = ERR_BULKBASE + 9; // Error building segment file list in a directory
const int ERR_BULK_BINARY_PARTIAL_REC = ERR_BULKBASE + 10;// Binary input did not end on fixed length record boundary
const int ERR_BULK_BINARY_IGNORE_FLD = ERR_BULKBASE + 11;// <IgnoreField> tag not supported for binary import
//--------------------------------------------------------------------------
// BRM error
//--------------------------------------------------------------------------
const int ERR_BRM_LOOKUP_LBID = ERR_BRMBASE + 1; // Lookup LBID error
const int ERR_BRM_LOOKUP_FBO = ERR_BRMBASE + 2; // Lookup FBO error
const int ERR_BRM_ALLOC_EXTEND = ERR_BRMBASE + 3; // Allocate extent error
const int ERR_BRM_COMMIT = ERR_BRMBASE + 4; // Commit error
const int ERR_BRM_ROLLBACK = ERR_BRMBASE + 5; // Rollback error
const int ERR_BRM_GET_UNCOMM_LBID = ERR_BRMBASE + 6; // Get uncommitted lbid list error
const int ERR_BRM_DEL_OID = ERR_BRMBASE + 7; // Delete oid error
const int ERR_BRM_BEGIN_COPY = ERR_BRMBASE + 8; // Begin copy error
const int ERR_BRM_END_COPY = ERR_BRMBASE + 9; // End copy error
const int ERR_BRM_GET_HWM = ERR_BRMBASE + 10;// Get hwm error
const int ERR_BRM_SET_HWM = ERR_BRMBASE + 11;// Set hwm error
const int ERR_BRM_WR_VB_ENTRY = ERR_BRMBASE + 12;// Write VB entry error
const int ERR_BRM_VB_COPY_READ = ERR_BRMBASE + 13;// VB copy read error
const int ERR_BRM_VB_COPY_SEEK_DB = ERR_BRMBASE + 14;// VB copy seek error to DB file
const int ERR_BRM_VB_COPY_SEEK_VB = ERR_BRMBASE + 15;// VB copy seek error to VB file
const int ERR_BRM_VB_COPY_WRITE = ERR_BRMBASE + 16;// VB copy write
const int ERR_BRM_DEAD_LOCK = ERR_BRMBASE + 17;// DEAD lock error
const int ERR_BRM_MARK_INVALID = ERR_BRMBASE + 18;// Mark extent invalid error from casual paritioning
const int ERR_BRM_SAVE_STATE = ERR_BRMBASE + 19;// Save state error
const int ERR_BRM_GET_START_EXTENT= ERR_BRMBASE + 20;// Get starting Extent error
const int ERR_BRM_VB_OVERFLOW = ERR_BRMBASE + 21;// Version buffer overflow
const int ERR_BRM_READ_ONLY = ERR_BRMBASE + 22;// BRM is in READ-ONLY state
const int ERR_BRM_GET_READ_WRITE = ERR_BRMBASE + 23;// error getting BRM READ/WRITE state
const int ERR_BRM_BULK_RB_COLUMN = ERR_BRMBASE + 24;// error during column bulk rollback
const int ERR_BRM_BULK_RB_DCTNRY = ERR_BRMBASE + 25;// error during dctnry bulk rollback
const int ERR_BRM_DELETE_EXTENT_COLUMN= ERR_BRMBASE + 26;// error during delete column extents
const int ERR_BRM_DELETE_EXTENT_DCTNRY= ERR_BRMBASE + 27;// error during delete dictionary extents
const int ERR_BRM_TAKE_SNAPSHOT = ERR_BRMBASE + 28;// Taking snapshot of BRM state
const int ERR_BRM_LOOKUP_START_LBID=ERR_BRMBASE + 29;// Lookup starting LBID error
const int ERR_BRM_BULK_UPDATE = ERR_BRMBASE + 30;// Error with bulk update of HWM and CP
const int ERR_BRM_GET_EXT_STATE = ERR_BRMBASE + 31;// Error getting extent state
const int ERR_EXTENTMAP_LOOKUP = ERR_BRMBASE + 32;// Lookup extent map error
const int ERR_BRM_LOOKUP_VERSION = ERR_BRMBASE + 33;// Lookup version error
const int ERR_BRM_LOOKUP_LBID_RANGES = ERR_BRMBASE + 34;// Lookup LBID Ranges error
const int ERR_BRM_HWMS_NOT_EQUAL = ERR_BRMBASE + 35;// HWMs of same col width not equal
const int ERR_BRM_HWMS_OUT_OF_SYNC= ERR_BRMBASE + 36;// HWMs for dif col width not in sync
const int ERR_BRM_DBROOT_HWMS = ERR_BRMBASE + 37;// Error getting HWMs for each DBRoot
const int ERR_BRM_NETWORK = ERR_BRMBASE + 38;// Network error when calling BRM functions
const int ERR_BRM_READONLY = ERR_BRMBASE + 39;// DBRM is readonly
const int ERR_INVALID_VBOID = ERR_BRMBASE + 40;// returned if the given vboid is invalid
const int ERR_BRM_SET_EXTENTS_CP = ERR_BRMBASE + 41;// Error setting extents min/max
const int ERR_BRM_SHUTDOWN = ERR_BRMBASE + 42;// BRM is set to shutdown
const int ERR_BRM_GET_SHUTDOWN = ERR_BRMBASE + 43;// error getting BRM Shutdown flag
const int ERR_BRM_SUSPEND = ERR_BRMBASE + 44;// BRM is set to Suspend writes
const int ERR_BRM_GET_SUSPEND = ERR_BRMBASE + 45;// error getting BRM Suspend flag
const int ERR_BRM_BAD_STRIPE_CNT = ERR_BRMBASE + 46;// Incorrect num of cols allocated in stripe
//--------------------------------------------------------------------------
// DM error
//--------------------------------------------------------------------------
const int ERR_DM_CONVERT_OID = ERR_DMBASE + 1; // Conversion error
//--------------------------------------------------------------------------
// Cache error
//--------------------------------------------------------------------------
const int ERR_CACHE_KEY_EXIST = ERR_CACHEBASE + 1; // Cache key exist
const int ERR_CACHE_KEY_NOT_EXIST = ERR_CACHEBASE + 2; // Cache key not exist
const int ERR_NULL_BLOCK = ERR_CACHEBASE + 3; // Block is NULL
const int ERR_FREE_LIST_EMPTY = ERR_CACHEBASE + 4; // Empty Free list
//--------------------------------------------------------------------------
// Compression error
//--------------------------------------------------------------------------
const int ERR_COMP_COMPRESS = ERR_COMPBASE + 1; // Error compressing data
const int ERR_COMP_UNCOMPRESS = ERR_COMPBASE + 2; // Error uncompressing data
const int ERR_COMP_PARSE_HDRS = ERR_COMPBASE + 3; // Error parsing compression headers
const int ERR_COMP_VERIFY_HDRS = ERR_COMPBASE + 4; // Error verifying compression headers
const int ERR_COMP_PAD_DATA = ERR_COMPBASE + 5; // Pad compressed data failed
const int ERR_COMP_READ_BLOCK = ERR_COMPBASE + 6; // Failed to read a block
const int ERR_COMP_SAVE_BLOCK = ERR_COMPBASE + 7; // Failed to save a block
const int ERR_COMP_WRONG_PTR = ERR_COMPBASE + 8; // Pointer in header is wrong
const int ERR_COMP_FILE_NOT_FOUND = ERR_COMPBASE + 9; // File not found in map
const int ERR_COMP_CHUNK_NOT_FOUND= ERR_COMPBASE + 10;// Chunk not found in map
const int ERR_COMP_UNAVAIL_TYPE = ERR_COMPBASE + 11;// Unavailable compression type
const int ERR_COMP_REMOVE_FILE = ERR_COMPBASE + 12;// Failed to remove a file
const int ERR_COMP_RENAME_FILE = ERR_COMPBASE + 13;// Failed to rename a file
const int ERR_COMP_OPEN_FILE = ERR_COMPBASE + 14;// Failed to open a compressed data file
const int ERR_COMP_SET_OFFSET = ERR_COMPBASE + 15;// Failed to set offset in a compressed data file
const int ERR_COMP_READ_FILE = ERR_COMPBASE + 16;// Failed to read from a compressed data file
const int ERR_COMP_WRITE_FILE = ERR_COMPBASE + 17;// Failed to write to a compresssed data file
const int ERR_COMP_CLOSE_FILE = ERR_COMPBASE + 18;// Failed to close a compressed data file
const int ERR_COMP_TRUNCATE_ZERO = ERR_COMPBASE + 19;// Invalid attempt to truncate file to 0 bytes
//--------------------------------------------------------------------------
// Auto-increment error
//--------------------------------------------------------------------------
const int ERR_AUTOINC_GEN_EXCEED_MAX = ERR_AUTOINCBASE + 1; // Generated autoinc value exceeds max auto increment value/
const int ERR_AUTOINC_USER_OUT_OF_RANGE=ERR_AUTOINCBASE + 2; // User specified autoinc value is out of range
const int ERR_AUTOINC_TABLE_NAME = ERR_AUTOINCBASE + 3; // Invalid schema/tablename for auto increment
const int ERR_AUTOINC_INIT1 = ERR_AUTOINCBASE + 4; // Error initializing auto increment (known exception)
const int ERR_AUTOINC_INIT2 = ERR_AUTOINCBASE + 5; // Error initializing auto increment (unknown exception)
const int ERR_AUTOINC_RID = ERR_AUTOINCBASE + 6; // Error initializing auto increment (unknown exception)
const int ERR_AUTOINC_START_SEQ = ERR_AUTOINCBASE + 7; // Error setting up an auto-increment sequence
const int ERR_AUTOINC_GET_RANGE = ERR_AUTOINCBASE + 8; // Error reserving an auto-increment range
const int ERR_AUTOINC_GET_LOCK = ERR_AUTOINCBASE + 9; // Error getting a lock to update auto-inc next value
const int ERR_AUTOINC_REL_LOCK = ERR_AUTOINCBASE +10; // Error releasing lock to update auto-inc next value
const int ERR_AUTOINC_UPDATE = ERR_AUTOINCBASE +11; // Error updating nextValue in system catalog
//--------------------------------------------------------------------------
// Block cache flush error
//--------------------------------------------------------------------------
const int ERR_BLKCACHE_FLUSH_LIST = ERR_BLKCACHEBASE + 1; // Error flushing list of blocks to PrimProc
//--------------------------------------------------------------------------
// Bulk backup metadata file and corresponding HWM compressed chunk files
//--------------------------------------------------------------------------
const int ERR_METADATABKUP_FILE_RENAME = ERR_METABKUPBASE + 1; // Error renaming meta file */
const int ERR_METADATABKUP_COMP_PARSE_HDRS = ERR_METABKUPBASE + 2; // Error parsing compression headers */
const int ERR_METADATABKUP_COMP_VERIFY_HDRS = ERR_METABKUPBASE + 3; // Error verifying compression headers */
const int ERR_METADATABKUP_COMP_CHUNK_NOT_FOUND= ERR_METABKUPBASE + 4; // Chunk not found in file */
const int ERR_METADATABKUP_COMP_OPEN_BULK_BKUP = ERR_METABKUPBASE + 5; // Error opening backup chunk file */
const int ERR_METADATABKUP_COMP_WRITE_BULK_BKUP= ERR_METABKUPBASE + 6; // Error writing to backup chunk file */
const int ERR_METADATABKUP_COMP_READ_BULK_BKUP = ERR_METABKUPBASE + 7; // Error reading from backup chunk file */
const int ERR_METADATABKUP_COMP_RENAME = ERR_METABKUPBASE + 8; // Error renaming chunk file */
//------------------------------------------------------------------------------
// Class used to convert an error code to a corresponding error message string
//------------------------------------------------------------------------------
struct WErrorCodes
{
EXPORT WErrorCodes();
EXPORT std::string errorString(int code);
private:
typedef std::map<int, std::string> CodeMap;
CodeMap fErrorCodes;
};
} //end of namespace
#undef EXPORT
#endif // _WE_DEFINE_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,582 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id: we_fileop.h 4737 2013-08-14 20:45:46Z bwilkinson $
/** @file */
#ifndef _WE_FILEOP_H_
#define _WE_FILEOP_H_
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <vector>
#include <map>
#include <boost/thread.hpp>
#ifdef _MSC_VER
#include <direct.h>
#define S_IRWXU 0
#define S_IRWXG 0
#ifndef S_IROTH
#define S_IROTH 0
#endif
#define S_IXOTH 0
#endif
#include "we_blockop.h"
#include "we_brm.h"
#include "we_config.h"
#include "we_stats.h"
#include "idbcompress.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
#include "brmtypes.h"
/** Namespace WriteEngine */
namespace WriteEngine
{
/** Class FileOp */
class FileOp : public BlockOp
{
public:
/**
* @brief Constructor
*/
EXPORT explicit FileOp(bool doAlloc=true);
/**
* @brief Destructor
*/
EXPORT virtual ~FileOp();
/**
* @brief Close a file
*/
EXPORT void closeFile( IDBDataFile* pFile ) const;
/**
* @brief Create a directory
*/
EXPORT int createDir( const char* dirName, mode_t mode ) const;
int createDir( const char* dirName ) const;
/**
* @brief Create a file with a fixed file size and file id
*/
EXPORT int createFile( FID fid,
int & allocSize,
uint16_t dbRoot, uint32_t partition,
execplan::CalpontSystemCatalog::ColDataType colDataType,
uint64_t emptyVal = 0, int width = 1 ) ;
/**
* @brief Delete a file
*/
EXPORT int deleteFile( const char* fileName ) const;
/**
* @brief Delete the db files corresponding to the specified file id
*/
EXPORT int deleteFile( FID fid ) const;
/**
* @brief Delete the db files corresponding to the specified file id
*/
EXPORT int deleteFiles( const std::vector<int32_t>& fids ) const;
/**
* @brief Delete db files corresponding to specified file id and partition
*/
EXPORT int deletePartitions( const std::vector<OID>& fids,
const std::vector<BRM::PartitionInfo>& partitions )
const;
/**
* @brief Delete a specific database segment file.
*/
EXPORT int deleteFile( FID fid, uint16_t dbRoot,
uint32_t partition,
uint16_t segment ) const;
/**
* @brief Check whether a file exists or not
*/
EXPORT bool exists( const char* fileName ) const;
/**
* @brief @brief Check whether file exists or not by using file id, DBRoot,
* partition, and segment number.
*/
EXPORT bool exists( FID fid, uint16_t dbRoot,
uint32_t partition, uint16_t segment ) const;
/**
* @brief Check whether a column exists or not by using file id. Since this
* is not enough to fully qualify a db filename, all it can do is to verify
* that the OID directory exists on one or more of the DBRoots.
*/
EXPORT bool existsOIDDir( FID fid ) const;
/**
* @brief Expand current abbreviated extent for this column to a full extent
*
* @param pFile FILE ptr of segment file we are updating.
* @param dbRoot DBRoot of the file being updated.
* @param emptyVal Empty value used in initializing extents for this column
* @param width Width of this column (in bytes)
*/
EXPORT virtual int expandAbbrevColumnExtent(
IDBDataFile* pFile,
uint16_t dbRoot,
uint64_t emptyVal,
int width );
/**
* @brief Add an extent to the specified Column OID and DBRoot.
* The extent must already exist in the extentmap prior to calling this fctn.
*
* The partition, segment, and HWM of the column file where the
* extent is added is returned. If needed, the applicable column segment
* file will be created. This extendFile1 function should supplant other
* extendFile functions with Multiple-File-per-OID enhancement, "but" we
* may want to rethink when we do Shared-Nothing. When this function
* returns, the file position will be located at the end of the file.
* For shared-everything DBRoot was an output argument, as BRM selected the
* the DBRoot. For shared-nothing DBRoot is an input argument, as the
* application code must track/control the DBRoot selection.
* If this is the very first file for the specified DBRoot, then the
* partition and segment number must be specified, else the selected
* partition and segment numbers are returned.
*
* @param oid OID of the column to be extended
* @param emptyVal Empty value to be used for oid
* @param width Width of the column
* @param hwm The fbo of the column segment file where the new extent begins
* @param startLbid The starting LBID for the new extent
* @param allocSize Number of blocks allocated to the extent.
* @param dbRoot The DBRoot of the file with the new extent.
* @param partition The partnum of the file with the new extent.
* @param segment The segnum of the file with the new extent.
* @param segFile (out) Name of the segment file where extent was added.
* @param pFile (out) FILE ptr to the file where the extent is added.
* @param newFile (out) Indicates if a new file was created for the extent
* @param hdrs (in/out) Contents of headers, if file is compressed.
* @return returns NO_ERROR if success.
*/
EXPORT int extendFile(OID oid, uint64_t emptyVal,
int width,
HWM hwm,
BRM::LBID_t startLbid,
int allocSize,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
std::string& segFile,
IDBDataFile*& pFile,
bool& newFile,
char* hdrs);
/**
* @brief For alter table add column; add an extent to a specific file
*
* @param oid OID of the column to be extended
* @param emptyVal Empty value to be used for oid
* @param width Width of the column
* @param allocSize (out) Number of blocks allocated to the extent.
* @param dbRoot The DBRoot of the file with the new extent.
* @param partition The partnum of the file with the new extent.
* @param segment The segnum of the file with the new extent.
* @param segFile (out) Name of the segment file where extent was added.
* @param startLbid (out) The starting LBID for the new extent
* @param newFile (out) Indicates if a new file was created for the extent
* @param hdrs (in/out) Contents of headers, if file is compressed.
*/
EXPORT int addExtentExactFile(OID oid, uint64_t emptyVal,
int width,
int& allocSize,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
execplan::CalpontSystemCatalog::ColDataType colDataType,
std::string& segFile,
BRM::LBID_t& startLbid,
bool& newFile,
char* hdrs);
/**
* @brief Pad the specified compressed extent with empty chunks
* @param oid OID of relevant column
* @param width Width in bytes of this column
* @param emptyVal Empty value to be employed in filling the chunks
* @param dbRoot DBRoot of the extent to be filled
* @param partition Partition of the extent to be filled
* @param segment Segment file number of the extent to be filled
* @param hwm New HWM blk setting for the segment file after extent is padded
* @param segFile (out) Name of updated segment file
* @param errTask (out) Task that failed if error occurs
* @return returns NO_ERROR if success.
*/
EXPORT int fillCompColumnExtentEmptyChunks(OID oid,
int colWidth,
uint64_t emptyVal,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
HWM hwm,
std::string& segFile,
std::string& errTask);
/**
* @brief Write the specified header info to compressed column file pFile.
*
* @param pFile Column file to be written to
* @param hdr Header info to be written
*/
EXPORT int writeHeaders(IDBDataFile* pFile, const char* hdr) const;
/**
* @brief Write the specified header info to compressed column or
* dictionary file pFile.
*
* @param pFile Column file to be written to
* @param controlHdr Control header info to be written
* @param pointerHdr Pointer header info to be written
* @param ptrHdrSize Size (in bytes) of pointerHdr
*/
EXPORT int writeHeaders(IDBDataFile* pFile,
const char* controlHdr,
const char* pointerHdr,
uint64_t ptrHdrSize) const;
/**
* @brief Get the Version Buffer filename for the specified fid (OID).
*
* This version of getFileName automatically uses 0 for the partition and
* segment numbers. The applicable DBRoot is assigned based on the OID.
*
* @param fid (in) OID of the Version Buffer DB file of interest
* @param fileName (out) the name of the pertinent file that was found
*
* @return returns NO_ERROR if success; ERR_FILE_NOT_EXIST if file not found
*/
int getVBFileName( FID fid, char* fileName ) const;
/**
* @brief Get the filename for the specified fid (OID). DBRoot, partition,
* and segment number.
*
* @param fid (in) OID of the DB file of interest
* @param fileName (out) the name of the pertinent file that was found
* @param dbRoot (in) DBRoot of the file of interest. If 0, then all the
* DBRoots will be searched.
* @param partition (in) partition number of the file of interest
* @param segment (in) segment number of the file of interest
*/
int getFileName( FID fid, char* fileName,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment ) const;
/**
* @brief Construct directory path for the specified fid (OID), DBRoot, and
* partition number. Directory does not have to exist, nor is it created.
*/
int getDirName( FID fid, uint16_t dbRoot,
uint32_t partition,
std::string& dirName) const;
/**
* @brief Get the file size
*/
EXPORT int getFileSize( IDBDataFile* pFile, long long& fileSize ) const;
EXPORT int getFileSize( FID fid, uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
long long& fileSize ) const;
/**
* @brief Initialize an extent in a dictionary store file
* @param pFile (in) IDBDataFile* of dictionary store file to be written to
* @param dbRoot (in) - DBRoot of pFile
* @param nBlocks (in) - number of blocks to be written for an extent
* @param blockHdrInit(in) - data used to initialize each block header
* @param blockHdrInitSize(in) - number of bytes in blockHdrInit
* @param bExpandExtent (in) - Expand existing extent, or initialize new one
*/
EXPORT int initDctnryExtent( IDBDataFile* pFile,
uint16_t dbRoot,
int nBlocks,
unsigned char* blockHdrInit,
int blockHdrInitSize,
bool bExpandExtent );
/**
* @brief Check whether it is an directory
*/
EXPORT bool isDir( const char* dirName ) const;
/**
* @brief See if there is room in the file system for specific number of blks
* @param fileName Name of file to extend (does not have to be full name)
* @param nBlocks Number of 8192-byte blocks to be added
* @return returns TRUE if file system has room for 'nBlocks', else FALSE
*/
EXPORT bool isDiskSpaceAvail(const std::string& fileName,
int nBlocks) const;
/**
* @brief Convert an oid to a full file name
*/
EXPORT int oid2FileName( FID fid, char* fullFileName,
bool bCreateDir, uint16_t dbRoot,
uint32_t partition, uint16_t segment ) const;
EXPORT int oid2DirName( FID fid, char* oidDirName ) const;
/**
* @brief Open a file using a filename.
* @param fileName Name of the file to open.
* @param mode Mode to use in opening the file (ex: "r+b").
* @param ioBuffSize Buffer size to be employed by setvbuf().
* @return returns the IDBDataFile* of the opened file.
*/
EXPORT IDBDataFile* openFile( const char* fileName,
const char* mode = "r+b",
int ioColSize = DEFAULT_COLSIZ,
bool useTmpSuffix = false) const;
/**
* @brief Open a file using an OID, dbroot, partition, and segment number.
* @param fid OID of the file to be opened.
* @param dbRoot DBRoot of the file to be opened.
* @param partition Partition number of the file to be opened.
* @param segment Segment number of the file to be opened.
* @param mode Mode to use in opening the file (default of "r+b" will open
* an existing binary file as read/write.
* @param ioBuffSize Buffer size to be employed by setvbuf().
* @return returns the IDBDataFile* of the opened file.
*/
EXPORT IDBDataFile* openFile( FID fid,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
std::string& segFile,
const char* mode = "r+b",
int ioColSize = DEFAULT_COLSIZ,
bool useTmpSuffix = false) const;
/**
* @brief Read to a buffer from a file at current location
*/
EXPORT int readFile( IDBDataFile* pFile, unsigned char* readBuf,
int readSize ) const;
/**
* @brief Reads in 2 compression header blocks from a column segment file.
* IDBDataFile* points to start of data when function returns.
* @param pFile (in) IDBDataFile* of column segment file to be read.
* @param hdrs (out) Contents of headers that are read.
*/
EXPORT int readHeaders( IDBDataFile* pFile, char* hdrs ) const;
EXPORT int readHeaders( IDBDataFile* pFile, char* hdr1, char* hdr2 )const;
/**
* @brief Reinitialize a partial extent in a column segment file
* @param pFile (in) IDBDataFile* of column segment file to be written to
* @param startOffset (in) - file offset where blocks are to be written
* @param nBlocks (in) - number of blocks to be written to the extent
* @param emptyVal(in) - empty value to be used for column data values
* width (in) - width of the applicable column
*/
EXPORT int reInitPartialColumnExtent( IDBDataFile* pFile,
long long startOffset,
int nBlocks,
uint64_t emptyVal,
int width );
/**
* @brief Reinitialize an extent in a dictionary store file
* @param pFile (in) IDBDataFile* of dictionary store file to be written to
* @param startOffset (in) - file offset where blocks are to be written
* @param nBlocks (in) - number of blocks to be written to the extent
* @param blockHdrInit(in) - data used to initialize each block header
* @param blockHdrInitSize(in) - number of bytes in blockHdrInit
*/
EXPORT int reInitPartialDctnryExtent( IDBDataFile* pFile,
long long startOffset,
int nBlocks,
unsigned char* blockHdrInit,
int blockHdrInitSize );
/**
* @brief Set the file to specified location based on the offset
*/
EXPORT int setFileOffset( IDBDataFile* pFile,
long long offset,
int origin = SEEK_SET ) const;
EXPORT int setFileOffsetBlock( IDBDataFile* pFile,
uint64_t lbid,
int origin = SEEK_SET ) const;
/**
* @brief Truncate the file to the specified file size
*/
EXPORT int truncateFile( IDBDataFile* pFile,
long long fileSize ) const;
/**
* @brief Write a buffer to a file at current location
*/
EXPORT int writeFile( IDBDataFile* pFile,
const unsigned char* buf, int bufSize ) const;
/**
* @brief set the flag to use the instance to access the brm wrapper class
*/
EXPORT virtual void setTransId( const TxnID& transId);
EXPORT virtual void setBulkFlag(bool isBulkLoad);
EXPORT virtual void setFixFlag(bool isFix);
TxnID getTransId() const;
void compressionType(int t);
int compressionType() const;
EXPORT virtual int flushFile(int rc, std::map<FID,FID> & oids);
protected:
EXPORT virtual int updateColumnExtent(IDBDataFile* pFile, int nBlocks);
EXPORT virtual int updateDctnryExtent(IDBDataFile* pFile, int nBlocks);
int m_compressionType; // compresssion type
private:
//not copyable
FileOp(const FileOp& rhs);
FileOp& operator=(const FileOp& rhs);
int createFile( const char* fileName, int fileSize,
uint64_t emptyVal, int width,
uint16_t dbRoot );
int expandAbbrevColumnChunk( IDBDataFile* pFile,
uint64_t emptyVal,
int colWidth,
const compress::CompChunkPtr& chunkInPtr,
compress::CompChunkPtr& chunkOutPt);
int initAbbrevCompColumnExtent( IDBDataFile* pFile,
uint16_t dbRoot,
int nBlocks,
uint64_t emptyVal,
int width);
// Initialize an extent in a column segment file
// pFile (in) IDBDataFile* of column segment file to be written to
// dbRoot (in) - DBRoot of pFile
// nBlocks (in) - number of blocks to be written for an extent
// emptyVal(in) - empty value to be used for column data values
// width (in) - width of the applicable column
// bNewFile (in) - Adding extent to new file
// bExpandExtent (in) - Expand existing extent, or initialize new one
// bAbbrevExtent (in) - If adding new extent, is it abbreviated
int initColumnExtent( IDBDataFile* pFile,
uint16_t dbRoot,
int nBlocks,
uint64_t emptyVal,
int width,
bool bNewFile,
bool bExpandExtent,
bool bAbbrevExtent );
static void initDbRootExtentMutexes();
static void removeDbRootExtentMutexes();
int writeInitialCompColumnChunk( IDBDataFile* pFile,
int nBlocksAllocated,
int nRows,
uint64_t emptyVal,
int width,
char* hdrs);
TxnID m_transId;
bool m_isBulk;
bool m_isFix;
// protect creation of m_DbRootAddExtentMutexes
static boost::mutex m_createDbRootMutexes;
// Mutexes used to serialize extent creation within each DBRoot
static std::map<int,boost::mutex*> m_DbRootAddExtentMutexes;
// protect race condition in creating directories
static boost::mutex m_mkdirMutex;
char* m_buffer; // buffer used with setvbuf()
};
//------------------------------------------------------------------------------
// Inline functions
//------------------------------------------------------------------------------
inline void FileOp::compressionType(int t)
{
m_compressionType = t;
}
inline int FileOp::compressionType() const
{
return m_compressionType;
}
inline int FileOp::createDir( const char* dirName ) const
{
return createDir( dirName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
}
inline int FileOp::getVBFileName( FID fid, char* fileName ) const
{
uint16_t dbRoot = 0;
uint32_t partition = 0;
uint16_t segment = 0;
return oid2FileName( fid, fileName, true, dbRoot, partition, segment );
}
inline int FileOp::getFileName( FID fid, char* fileName,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment ) const
{
return oid2FileName( fid, fileName, false, dbRoot, partition, segment );
}
inline TxnID FileOp::getTransId() const
{
return m_transId;
}
} //end of namespace
#undef EXPORT
#endif // _WE_FILEOP_H_

View File

@ -0,0 +1,351 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/******************************************************************************************
* $Id: we_index.h 4450 2013-01-21 14:13:24Z rdempsey $
*
******************************************************************************************/
/** @file */
#ifndef _WE_INDEX_H_
#define _WE_INDEX_H_
#include <bitset>
#include "we_type.h"
/** Namespace WriteEngine */
namespace WriteEngine
{
/*****************************************************
* index definition
******************************************************/
const int IDX_BITTEST_SIZE = 10; /** @brief The bit size of bit test */
const int IDX_GROUP_SIZE = 3; /** @brief The bit size of group */
const int IDX_INSTRU_SIZE = 4; /** @brief The bit size of instruction */
const int IDX_PTR_SIZE = 46; /** @brief The bit size of address pointer */
const int IDX_TYPE_SIZE = 3; /** @brief The bit size of type */
const int IDX_BITMAP_SUBBLOCK_NO = 1; /** @brief Subblock 1 of root block is for bitmap pointer*/
const int IDX_MAX_TREE_LEVEL = 128; /** @brief The maximum depth of a tree */
const int IDX_MAX_MULTI_COL_BIT = 256; /** @brief The maximum bits of a multi-column tree (256 bit)*/
const int IDX_MAX_MULTI_COL_IDX_LEVEL = 52; /** @brief The maximum depth of a multi-column tree */
const int IDX_MAX_MULTI_COL_IDX_NUM = 64; /** @brief The maximum number of columns for a multi-column index */
const int MAX_IDX_RID = 1024; /** @brief Maximum index rids for one shot */
const int IDX_DEFAULT_READ_ROW = 10000; /** @brief Default number of rows for one read for index */
// todo: need to move a higher level share file for dictionary
const int RID_SIZE = 46;
// const int OID_SIZE = 24; /** @brief The bit size of object id */
const int FBO_SIZE = 36; /** @brief The bit size of file block offset */
const int SBID_SIZE = 5; /** @brief The bit size of sub block id */
const int ENTRY_SIZE = 5; /** @brief The bit size of entry location with a sub block */
const int LIST_SIZE_TYPE = 0;
const int LIST_RID_TYPE = 3;
const int LIST_NOT_USED_TYPE = 7;
const int LIST_HDR_SIZE = 32;
const int LIST_SUBBLOCK_TYPE = 4 ;
const int LIST_BLOCK_TYPE = 5 ;
const int LIST_LLP_TYPE = 6 ;
const int SUBBLOCK_TOTAL_BYTES = 256;
const int LIST_SUB_LLP_POS = 31;
const int LIST_LAST_LBID_POS = 30;
const int LIST_BLOCK_LLP_POS = 1023;
const int MAX_BLOCK_ENTRY = 1024;
const int MAX_SUB_RID_CNT = 30;
const int MAX_BLK_RID_CNT = 1023;
const int MAX_BLK_NARRAY_RID_CNT = 1018;
const int LBID_SBID_ENTRY = 46;
const int RID_COUNT_SIZE = 10;
const int CUR_BLK_POS_WIDTH = 2;
const int LLP_STATUS_WIDTH = 2;
const int LIST_ENTRY_WIDTH = 8;
const int LIST_BLK_LLP_ENTRY_WIDTH= 48;
const int BEGIN_LIST_BLK_LLP_POS = 1018;
const int NEXT_BLK_PTR_OFFSET = 5;
const int PARENT_PTR_OFFSET = 4;
const int TOTAL_NUM_ARRAY_PTR = 4;
const int ARRAY_LLP_EXIST = 1;
const int LLP_NOT_FULL = 0;
const int LLP_FULL = 1;
const int TOTAL_CUR_LEVEL = 10;
const int CUR_LEVEL_POS_WIDTH = 20;
const uint64_t INVALID_KEY = -1LL; /** @brief Invalid number */
/*****************************************************
* mask definition
******************************************************/
const int BIT_MASK_ARRAY[] = { 0x0,
0x01, /** @brief 1 bit mask */
0x03, /** @brief 2 bit mask */
0x07, /** @brief 3 bit mask */
0x0F, /** @brief 4 bit mask */
0x1F, /** @brief 5 bit mask */
0x3F /** @brief 6 bit mask */
};
/************************************************************************
* Type enumerations
************************************************************************/
enum IdxTreeEntryType { /** @brief Index tree entry types */
EMPTY_ENTRY = 0, /** @brief Empty entry */
UNIQUE_VAL = 7, /** @brief Unique value */
EMPTY_LIST = 1, /** @brief Empty list pointer entry */
EMPTY_PTR = 2, /** @brief Empty pointer entry */
BIT_TEST = 3, /** @brief Bit test entry */
LEAF_LIST = 4, /** @brief Leaf list pointer */
BITMAP_PTR = 5, /** @brief Bitmap pointer */
// SORT_LIST = 5, /** @brief Sorted list pointer */
MULTI_COL = 6 /** @brief Multi-column index pointer */
};
enum IdxTreeGroupType { /** @brief Index tree group types */
ENTRY_1 = 0, /** @brief 1 entry per group */
ENTRY_2 = 1, /** @brief 2 entry per group */
ENTRY_4 = 2, /** @brief 4 entry per group */
ENTRY_8 = 3, /** @brief 8 entry per group */
ENTRY_16 = 4, /** @brief 16 entry per group */
ENTRY_32 = 5, /** @brief 32 entry per group */
ENTRY_BLK = 6 /** @brief 1k entry per group */
};
enum IdxBitCompareType { /** @brief Index bit compare types */
BIT_5 = 0, /** @brief 5-bit compare */
BIT_10 = 1 /** @brief 10-bit compare */
};
enum IdxFreeMgrType { /** @brief Index free manager types */
TREE = 0, /** @brief Index tree type */
LIST = 1 /** @brief Index list type */
};
/************************************************************************
* @brief index defintions
************************************************************************/
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 12; /** @brief spare bits */
uint64_t group : IDX_GROUP_SIZE; /** @brief entry group type */
// The following is related to ptr
uint64_t fbo : FBO_SIZE; /** @brief file block offset */
uint64_t sbid : SBID_SIZE; /** @brief sub block id */
uint64_t entry : ENTRY_SIZE; /** @brief entry within sub block */
} IdxStartSubBlockEntry; /** @brief Index start block entry structure */
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 2; /** @brief spare bits */
uint64_t group : IDX_GROUP_SIZE; /** @brief entry group type */
// The following is related to ptr
uint64_t spare2 : 10; /** @brief spare bits */
uint64_t fbo : FBO_SIZE; /** @brief file block offset */
uint64_t sbid : SBID_SIZE; /** @brief sub block id */
uint64_t entry : ENTRY_SIZE; /** @brief entry within sub block */
} IdxEmptyListEntry; /** @brief Index empty list entry structure */
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 15; /** @brief spare bits */
// The following is related to ptr
uint64_t fbo : FBO_SIZE; /** @brief file block offset */
uint64_t sbid : SBID_SIZE; /** @brief sub block id */
uint64_t entry : ENTRY_SIZE; /** @brief entry within sub block */
} IdxBitmapPointerEntry; /** @brief Index bitmap pointer entry structure */
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t bitTest : IDX_BITTEST_SIZE; /** @brief index bittest */
uint64_t group : IDX_GROUP_SIZE; /** @brief entry group type */
uint64_t bitCompare : 1;
uint64_t spare : 1; /** @brief spare bits */
// The following is related to ptr
uint64_t fbo : FBO_SIZE; /** @brief file block offset */
uint64_t sbid : SBID_SIZE; /** @brief sub block id */
uint64_t entry : ENTRY_SIZE; /** @brief entry within sub block */
} IdxBitTestEntry; /** @brief Index bit test entry structure */
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 15; /** @brief spare bits */
// The following is related to ptr
uint64_t fbo : FBO_SIZE; /** @brief file block offset */
uint64_t sbid : SBID_SIZE; /** @brief sub block id */
uint64_t entry : ENTRY_SIZE; /** @brief entry within sub block */
} IdxTreePointerEntry; /** @brief Index tree pointer entry structure */
/************************************************************************
* @brief index list node defintions
************************************************************************/
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type 3 */
uint64_t spare : 15; /** @brief spare bits */
RID rid : RID_SIZE; /** @brief row id */
} IdxRidListEntry; /** @brief Index rid list entry structure */
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 5;
uint64_t count : RID_COUNT_SIZE; /** the count of rids on the current blk */
uint64_t llp : LBID_SBID_ENTRY; /** @brief size */
} IdxRidListPtr;
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 5;
uint64_t count : RID_COUNT_SIZE; /** the count of rids on the current blk */
uint64_t lbid : FBO_SIZE; /** @brief size */
uint64_t sbid : SBID_SIZE; /** @brief sub block id */
uint64_t entry : ENTRY_SIZE; /** @brief entry within sub block */
} IdxRidLastListPtr;
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 13;
uint64_t llpStat : LLP_STATUS_WIDTH; /** llp status */
uint64_t childLbid : FBO_SIZE; /** @brief file block offset */
uint64_t spare2 : 10;
} IdxRidChildListPtr;
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type 0 or 6 */
uint64_t spare : 5;
uint64_t count : RID_COUNT_SIZE; /** the count of rids on the current blk */
uint64_t nextLbid : FBO_SIZE; /** @brief file block offset */
uint64_t curLevel : TOTAL_CUR_LEVEL;
} IdxRidNextListPtr;
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type 6*/
uint64_t spare : 3; /** @brief spare bits */
uint64_t curLevelPos : CUR_LEVEL_POS_WIDTH;
uint64_t curBlkPos : CUR_BLK_POS_WIDTH; /** the position of current blk */
uint64_t parentLbid : FBO_SIZE; /** @brief file block offset */
} IdxRidParentListPtr;
typedef struct {
IdxRidChildListPtr childIdxRidListPtr[4];
IdxRidParentListPtr parentIdxListPtr;
IdxRidNextListPtr nextIdxListPtr;
} IdxRidListArrayPtr;
/************************************************************************
* @brief index list header defintions
************************************************************************/
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 15; /** @brief spare bits */
uint64_t size : RID_SIZE; /** @brief size */
} IdxRidListHdrSize;
typedef struct {
uint64_t type : IDX_TYPE_SIZE; /** @brief entry type */
uint64_t spare : 15; /** @brief spare bits */
uint64_t llp : RID_SIZE; /** @brief size */
} IdxRidListHdrPtr;
typedef struct {
IdxRidListHdrSize idxRidListSize;
uint64_t key;
IdxRidListEntry firstIdxRidListEntry;
IdxRidListHdrPtr nextIdxRidListPtr;
} IdxRidListHdr;
typedef struct {
uint64_t part1 : 15; /** @brief entry type */
uint64_t part2 : 15; /** @brief spare bits */
uint64_t spare : 34; /** @brief size */
} IdxRidListOffSet;
/************************************************************************
* @brief index tree node defintions
************************************************************************/
typedef struct {
IdxBitTestEntry next; /** @brief next in the node */
IdxBitTestEntry current; /** @brief current addr */
uint16_t level; /** @brief tree level */
uint16_t allocCount; /** @brief allocated entry cound from free mgr */
uint16_t useCount; /** @brief actual use entry count */
uint16_t offset; /** @brief entry offset */
bool used; /** @brief used flag */
} IdxTreeNode; /** @brief Index tree node */
typedef struct {
IdxTreeNode node[IDX_MAX_TREE_LEVEL]; /** @brief node array */
uint16_t maxLevel; /** @brief max level */
RID rid; /** @brief current row id */
uint64_t key; /** @brief current key */
uint16_t width; /** @brief current width */
} IdxTree; /** @brief Index tree */
struct IdxTreeCacheNode {
RID rid; /** @brief RID */
uint64_t key; /** @brief Key */
IdxEmptyListEntry entry; /** @brief List pointer */
bool used; /** @brief Used flag */
IdxTreeCacheNode() { used = false; }
};
struct IdxMultiColKey {
std::bitset<IDX_MAX_MULTI_COL_BIT> bitSet; /** @brief BitArray for all bits */
std::bitset<IDX_MAX_MULTI_COL_BIT> curBitset;/** @brief Current working column */
std::bitset<IDX_MAX_MULTI_COL_BIT> curMask; /** @brief Current bitset mask */
unsigned char keyBuf[IDX_MAX_MULTI_COL_BIT/8]; /** @brief Key buffer */
int curLevel; /** @brief Current index level */
int maxLevel; /** @brief Maximum index level */
int totalBit; /** @brief Total bits */
int testbitArray[IDX_MAX_MULTI_COL_IDX_LEVEL]; /** @brief Test bit array */
void clear() { bitSet.reset(); curBitset.reset(); curMask.reset();
curLevel = maxLevel = 0; totalBit = 0;
memset( testbitArray, 0, IDX_MAX_MULTI_COL_IDX_LEVEL); memset( keyBuf, 0, IDX_MAX_MULTI_COL_BIT/8 );
curMask = 0x1F; curMask = curMask << (IDX_MAX_MULTI_COL_BIT - 5);
}
IdxMultiColKey() { clear(); }
};
struct IdxMultiRid {
RID* ridArray; /** @brief RID array */
int totalRid; /** @brief Total number of row id */
IdxMultiRid() { totalRid = 0; ridArray = NULL; }
void setMultiRid( RID* rids, const int size ) {
totalRid = size;
ridArray = rids;
/* ridArray = new RID[size];
memcpy( ridArray, rids, size * sizeof( RID ) ); */
}
void clearMultiRid() { /*if( ridArray != NULL ) delete [] ridArray; ridArray = NULL;*/ } // we don't want to get into this mem business
};
struct IdxLoadParam {
File sourceFile; /** @brief Source file contatin values */
OID indexTreeOid; /** @brief Target index tree oid */
OID indexListOid; /** @brief Target index list oid */
execplan::CalpontSystemCatalog::ColDataType indexColDataType; /** @brief Target index column type */
int indexWidth; /** @brief Target index width */
int maxLoadRow; /** @brief Max rows for one load */
void setIdxLoadParam( const OID treeOid, const OID listOid, const execplan::CalpontSystemCatalog::ColDataType colDataType, const int width, const int maxRow )
{ indexTreeOid = treeOid; indexListOid = listOid; indexColDataType = colDataType;
indexWidth = width; maxLoadRow = maxRow; }
bool isValid() { return indexTreeOid && indexListOid && indexWidth && maxLoadRow; }
IdxLoadParam() { indexTreeOid = indexListOid = indexWidth = maxLoadRow = 0; }
};
} //end of namespace
#endif // _WE_INDEX_H_

View File

@ -0,0 +1,244 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_log.cpp 4504 2013-02-02 00:07:43Z bpaul $
*
*******************************************************************************/
#include "we_log.h"
#include "messageids.h"
#include "we_define.h"
#include "we_simplesyslog.h"
#include "we_convertor.h"
namespace WriteEngine
{
WriteEngine::WErrorCodes ec; // referenced as extern by chunkmanager
//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
Log::Log() : m_bConsoleOutput( true ),
m_logFileName( "" ),
m_errlogFileName( "" )
{
m_pid = ::getpid();
}
//------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------
Log::~Log()
{
m_logFile.close();
m_errLogFile.close();
}
//------------------------------------------------------------------------------
// DESCRIPTION:
// Format a message to be logged
// PARAMETERS:
// msg - message
// level - message level
// oss - formatted msg
// code - return status code to include in the message
// RETURN:
// none
//------------------------------------------------------------------------------
void Log::formatMsg( const std::string& msg,
MsgLevel level,
std::ostringstream& oss,
int code ) const
{
// Constructing and logging the entire message as one string, should
// help avoid any thread contention that could cause logging output
// to be interweaved between threads.
oss << Convertor::getTimeStr();
// Include thread id in log message based on debug level
if (isDebug( DEBUG_2 ))
{
oss << " (" << m_pid << ":" <<
#ifdef _MSC_VER
GetCurrentThreadId()
#else
pthread_self()
#endif
<< ") " <<
MSG_LEVEL_STR[level] << " : " << msg ;
}
else
{
oss << " (" << m_pid << ") " << MSG_LEVEL_STR[level] << " : " << msg ;
}
if( code > 0 )
oss << " [" << code << "]";
}
//------------------------------------------------------------------------------
// DESCRIPTION:
// Log a message to the log file and to the console.
// We used to log error and critical error msgs to error log only.
// But changed to log to m_logFile too, because it's easy to
// forget to look at the err log. And seeing the error log msg
// in the correct timeline context in the m_logFile helps to see
// what else was going on when the problem occurred.
// PARAMETERS:
// msg - message
// code - return status code to include in the message
// level - message level
// RETURN:
// none
//------------------------------------------------------------------------------
void Log::logMsg( const char* msg,
int code,
MsgLevel level )
{
std::ostringstream oss;
formatMsg( msg, level, oss, code );
// log error and critical msgs to syslog
if( level == MSGLVL_ERROR || level == MSGLVL_CRITICAL )
{
{ //log to log file and error log file within scope of mutex lock.
//logSyslog uses SimpleSyslog which has it's own lock.
boost::mutex::scoped_lock lk(m_WriteLockMutex);
m_errLogFile << oss.str() << std::endl;
m_logFile << oss.str() << std::endl;
std::cerr << oss.str() << std::endl;
}
logSyslog( std::string(msg), code );
}
else
{
std::ostringstream oss2;
// Format msg again without including the status code.
// Only log INFO2 msgs to console if m_bConsoleOutput is TRUE;
// All other msg levels always go to console.
if( (level != MSGLVL_INFO2) || (m_bConsoleOutput) )
formatMsg ( msg, level, oss2 );
boost::mutex::scoped_lock lk(m_WriteLockMutex);
m_logFile << oss.str() << std::endl;
if( (level != MSGLVL_INFO2) || (m_bConsoleOutput) )
std::cout << oss2.str() << std::endl;
}
}
//------------------------------------------------------------------------------
// DESCRIPTION:
// Set log file name
// PARAMETERS:
// logfile - log file name
// errlogfile - error log file name
// RETURN:
// none
//------------------------------------------------------------------------------
void Log::setLogFileName( const char* logfile,
const char* errlogfile,
bool consoleFlag )
{
m_logFileName = logfile;
m_errlogFileName = errlogfile;
m_bConsoleOutput = consoleFlag;
#ifdef _MSC_VER
// cpimport.bin calls BulkLoad::loadJobInfo() before calling
// BulkLoad::processJob(). loadJobInfo() attempts to write to this log
// before it's opened (by processJob()). This doesn't seem to bother Linux
// but puts Windows in a bad state. Once this logic is fixed, this hack can
// go away.
// This code probably wouldn't hurt if run on Linux, but I'll leave this
// here as a reminder to fix the logic for all platforms.
m_logFile.close();
m_logFile.clear();
m_errLogFile.close();
m_errLogFile.clear();
#endif
m_logFile.open( m_logFileName.c_str(),
std::ofstream::out | std::ofstream::app );
m_errLogFile.open(m_errlogFileName.c_str(),
std::ofstream::out | std::ofstream::app);
}
//------------------------------------------------------------------------------
// DESCRIPTION:
// Log specified (error or critical) message to syslog error log.
// PARAMETERS:
// msg - message
// statusCode - WriteEngine return status code to include in the message
// RETURN:
// none
//------------------------------------------------------------------------------
void Log::logSyslog( const std::string& msg,
int statusCode )
{
logging::Message::MessageID msgId = logging::M0087;
switch (statusCode)
{
case ERR_FILE_DISK_SPACE:
{
msgId = logging::M0076;
break;
}
case ERR_UNKNOWN:
{
msgId = logging::M0017;
break;
}
default:
{
msgId = logging::M0087;
break;
}
}
logging::Message::Args errMsgArgs;
errMsgArgs.add( msg );
SimpleSysLog::instance()->logMsg(
errMsgArgs,
logging::LOG_TYPE_ERROR,
msgId);
}
//------------------------------------------------------------------------------
// DESCRIPTION:
// BUG 5022
// Close the log files with out calling d'tor. That way we can use the
// object again for logging while importing another table or so
// PARAMETERS:
// none
// RETURN:
// none
//------------------------------------------------------------------------------
void Log::closeLog()
{
m_logFile.close();
m_errLogFile.close();
}
} //end of namespace

120
writeengine/shared/we_log.h Normal file
View File

@ -0,0 +1,120 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_log.h 4504 2013-02-02 00:07:43Z bpaul $
*
*******************************************************************************/
/** @file */
#ifndef _WE_LOG_H_
#define _WE_LOG_H_
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <we_obj.h>
#include <boost/thread.hpp>
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
const std::string MSG_LEVEL_STR[] = {
"INFO",
"INFO",
"WARN",
"ERR ",
"CRIT" };
/** @brief Class is used to format and write log messages to cpimport.bin log
* file. When applicable, messages are also logged to syslog logs as well.
*/
class Log : public WEObj
{
public:
/**
* @brief Constructor
*/
EXPORT Log();
/**
* @brief Destructor
*/
EXPORT ~Log();
/**
* @brief Log a cpimport.bin logfile message; logs errors to syslog as well
*/
EXPORT void logMsg( const char* msg, int code, MsgLevel level );
EXPORT void logMsg( const char* msg, MsgLevel level )
{ logMsg( msg, 0, level ); }
EXPORT void logMsg( const std::string& msg, MsgLevel level )
{ logMsg( msg.c_str(), level ); }
EXPORT void logMsg( const std::string& msg, int code, MsgLevel level )
{ logMsg( msg.c_str(), code, level ); }
/**
* @brief Set log file name
*/
EXPORT void setLogFileName( const char* logfile,
const char* errlogfile,
bool consoleFlag = true );
// BUG 5022
/**
* @brief Set log files close other than calling d'tor
*/
EXPORT void closeLog();
private:
void logSyslog ( const std::string& msg,
int statusCode);
void formatMsg( const std::string& msg,
MsgLevel level,
std::ostringstream& oss,
int code = 0 ) const;
bool m_bConsoleOutput; // flag allowing INFO2 msg
// to display to console
std::string m_logFileName; // log file name
std::string m_errlogFileName; // error log file name
pid_t m_pid; // current pid
std::ofstream m_logFile; // log file stream
std::ofstream m_errLogFile; // error log file stream
boost::mutex m_WriteLockMutex; // logging mutex
};
} //end of namespace
#undef EXPORT
#endif // _WE_LOG_H_

View File

@ -0,0 +1,53 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/******************************************************************************************
* $Id: we_macro.h 33 2006-10-18 14:37:12Z wzhou $
*
******************************************************************************************/
/** @file */
#ifndef _WE_MACRO_H_
#define _WE_MACRO_H_
#include <we_type.h>
/** Namespace WriteEngine */
namespace WriteEngine
{
#define RETURN_ON_ERROR( statement ) \
{ int rcVal = (statement); \
if( rcVal != NO_ERROR ) \
return rcVal; }
#define RETURN_ON_NULL( obj, rc ) \
if( obj == NULL ) \
return rc;
#define RETURN_ON_WE_ERROR( oldRc, newRc ) \
if( oldRc != NO_ERROR ) \
return newRc;
#define RETURN_RC( oldRc, newRc ) \
if( oldRc != NO_ERROR ) \
return newRc; \
else \
return NO_ERROR;
} //end of namespace
#endif // _WE_MACRO_H_

View File

@ -0,0 +1,81 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/******************************************************************************************
* $Id: we_obj.h 33 2006-08-17 10:31:20Z wzhou $
*
******************************************************************************************/
/** @file */
#ifndef _WE_OBJ_H_
#define _WE_OBJ_H_
//#include <we_type.h>
#include <we_macro.h>
/** Namespace WriteEngine */
namespace WriteEngine
{
class Log;
/** Class WEObj */
class WEObj
{
public:
/**
* @brief Constructor
*/
WEObj() : m_debugLevel( DEBUG_0 ), m_log( 0 ) {}
/**
* @brief Default Destructor
*/
~WEObj() {}
/**
* @brief Is it required to debug
*/
const bool isDebug( const DebugLevel level ) const { return level <= m_debugLevel; }
/**
* @brief Get debug level
*/
const DebugLevel getDebugLevel() const { return m_debugLevel; }
/**
* @brief Get Logger object
*/
Log* getLogger() const { return m_log; }
/**
* @brief Set debug level
*/
void setDebugLevel( const DebugLevel level ) { m_debugLevel = level; }
/**
* @brief Set debug logger and debug level
*/
void setLogger( Log* logger ) { m_log = logger; }
private:
DebugLevel m_debugLevel; // internal use debug level
Log* m_log; // logger object for debug output
};
} //end of namespace
#endif // _WE_OBJ_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*
* $Id: we_rbmetawriter.h 4450 2013-01-21 14:13:24Z rdempsey $
*/
/** @file we_rbmetawriter.h
* Contains class to write HWM-related information used to rollback a
* cpimport.bin job that abnormally terminated, leaving the db in an
* inconsistent state.
* Class was moved from bulk directory for resuse by DML as part of Shared
* Nothing.
*/
#ifndef WE_RBMETAWRITER_H_
#define WE_RBMETAWRITER_H_
#include <string>
#include <sstream>
#include <set>
#include <map>
#include <vector>
#include <boost/thread/mutex.hpp>
#include "we_type.h"
#include "brmtypes.h"
#include "we_fileop.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
#define DBROOT_BULK_ROLLBACK_SUBDIR "bulkRollback"
namespace WriteEngine
{
class Log;
//------------------------------------------------------------------------------
/** @brief Class used to store Dictionary store file information used in backing
* up HWM chunks "as needed".
*/
//------------------------------------------------------------------------------
struct RBChunkInfo
{
OID fOid; // dctnry store OID containing relevant chunk
uint16_t fDbRoot; // dbroot, partition, segment of file
uint32_t fPartition; // containing relevant HWM chunk
uint16_t fSegment; //
HWM fHwm; // HWM block of interest
RBChunkInfo(OID oid, uint16_t dbRoot, uint32_t partition,
uint16_t segment, HWM hwm ) :
fOid(oid), fDbRoot(dbRoot), fPartition(partition),
fSegment(segment), fHwm(hwm) { }
};
class RBChunkInfoCompare
{
public:
bool operator()(const RBChunkInfo& lhs, const RBChunkInfo& rhs) const;
};
typedef std::set< RBChunkInfo, RBChunkInfoCompare > RBChunkSet;
//------------------------------------------------------------------------------
/** @brief Class to write HWM-related information to support bulk rollbacks.
*
* Should cpimport.bin terminate abnormally, leaving the db in an inconsistent
* state, then the information written by this class can be used to perform
* a bulk rollback, to restore the db to its previous state, prior to the
* execution of the import job.
*
* For SharedEveryThing:
* Note that column segment files, carry a logical concatenation of extents,
* so only the HWM of the last logical extent needs to be written to the meta
* data file, as the information about where the data stops (and needs to
* be rolled back) for the other segment files can be derived from knowing
* the last Local HWM.
*
* For Shared-Nothing:
* Column segment files only carry a logical concatenation of extents, within
* a DBRoot. So the HWM of the last logical extent in each DBRoot (for a PM)
* must be written to the meta data file. The information about where the data
* stops (and needs to be rolled back) for the other segment files within a
* DBRoot can be derived from knowing the last Local HWM per DBRoot.
* One meta data control file is created for each DBRoot, and in fact, the
* meta file is created under the corresponding DBRoot directory.
*
* In the case of dictionary store segment files, each store file is
* independent of the other segment store files for the same OID. So for
* dictionary store segment files, the HWM must be written for each segment
* file in the last partition for each DBRoot.
*
* API Usage:
* Public functions would typically be called in the following order:
* 1. Create and initialize Bulk Rollback Metadata object:
* RBMetaWriter()
* init()
* 2. Create primary meta data file (see note below);
* openMetaFile()
* writeColumnMetaData()
* writeDictionaryStoreMetaData()
* writeDictionaryStoreMetaNoDataMarker()
* closeMetaFile()
* 3. Backup necessary HWM chunks to backup chunk files:
* a. backupColumnHWMChunk()
* b. backupDctnryHWMChunk()
* 4. Delete meta data file and HWM chunk files at end of successful job:
* deleteFile()
* 5. Delete Bulk Rollback Metadata object:
* ~RBMetaWriter()
*
* Steps 2 and 3a have been replaced with a single call to saveBulkRollback-
* MetaData(). This is a helper function that takes care of all the calls in
* steps 2 and 3a. If an error should occur in saveBulkRollbackMetaData(),
* closeMetaFile() will automatically be called to close the meta data file.
*
* backupDctnryHWMChunk() must be thread-safe as step 3b can be executed in
* parallel by several threads for different dictionary columns.
*/
//------------------------------------------------------------------------------
class RBMetaWriter
{
public:
/** @brief RBMetaWriter constructor
* @param appDesc Description of application that is using RBMetaWriter
* @param logger Logger to be used for logging messages.
*/
EXPORT RBMetaWriter ( const std::string& appDesc,
Log* logger );
/** @brief RBMetaWriter destructor
*/
EXPORT ~RBMetaWriter ( ) { closeMetaFile ( ); }
/** @brief Initialize this RBMetaWriter object
* Warning: This function may throw a WeException.
*
* @param tableOID OID of the table whose state is to be saved.
* @param tableName Name of the table associated with tableOID.
*/
EXPORT void init ( OID tableOID,
const std::string& tableName );
/** @brief Make a backup copy of the specified HWM dictionary store chunk.
* This operation only applies to compressed columns. Backup may not be
* necessary. Return value indicates whether the specified file needs to
* be backed up or not.
* Warning: This function may throw a WeException.
*
* This function is thread-safe since concurrent calls could be made by
* different threads, each for a different dictionary column.
*
* @param dctnryOID column OID to be saved
* @param dbRoot current dbRoot of last local HWM for columnOID
* @param partition current partition of last local HWM for columnOID
* @param segment current segment of last local HWM for columnOID
* @return Indicates whether it is necessary to perform backup
*/
EXPORT bool backupDctnryHWMChunk (
OID dctnryOID,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment );
/** @brief Delete the rollback meta files associated with this table
* Warning: This function may throw a WeException.
*/
EXPORT void deleteFile ( );
/** @brief Helper function that creates the primary meta data file.
* Warning: This function may throw a WeException.
*
* See class description for more details.
* @param columns Vector of column information. The dataFile member in
* each columns entry should be filled in with HWM information about
* the start extent where rows will be added. This information is
* needed so that the HWM chunk in that extent can be backed up.
* @param dctnryStoreOids Vector of dictionary store OID associated with
* columns vector. dctnryStoreOid[n] should be 0 if columns[n] is
* not a dictionary column.
* @param dbRootHwmInfoVecCol Vector of EmDbRootHWMInfo_v objects obtained
* from multiple calls to DBRM::getDbRootHWMInfo(). There is one
* EmDbRootHWMInfo_v entry per column. Each
* EmDbRootHWMInfo_v object carries a vector of DBRoot, HWM, etc
* objects representing the current HWM extents for a column's
* DBRoots on the local PM.
*/
EXPORT void saveBulkRollbackMetaData(
const std::vector<Column>& columns,
const std::vector<OID>& dctnryStoreOids,
const std::vector<BRM::EmDbRootHWMInfo_v>& dbRootHWMInfoVecCol );
/** @brief Verify that specified version record is for Version 3 */
static bool verifyVersion3(const char* versionRec);
/** @brief Verify that specified version record is for Version 4 */
static bool verifyVersion4(const char* versionRec);
/** @brief Verify that specified record type is a Column1 record */
static bool verifyColumn1Rec(const char* recType);
/** @brief Verify that specified record type is a Column2 record */
static bool verifyColumn2Rec(const char* recType);
/** @brief Verify that specified record type is a DStore1 record */
static bool verifyDStore1Rec(const char* recType);
/** @brief Verify that specified record type is a DStore2 record */
static bool verifyDStore2Rec(const char* recType);
private:
// disable copy constructor and assignment operator
RBMetaWriter(const RBMetaWriter&);
RBMetaWriter& operator=(const RBMetaWriter&);
// Make a backup copy of the specified HWM column chunk.
// This operation only applies to compressed columns.
// Warning: This function may throw a WeException.
// columnOID column OID to be saved
// dbRoot current dbRoot of last local HWM for columnOID
// partition current partition of last local HWM for columnOID
// segment current segment of last local HWM for columnOID
// lastLocalHwm current last local for column OID
void backupColumnHWMChunk (
OID columnOID,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
HWM lastLocalHwm );
// This function must be thread-safe since it is called directly by
// backupDctnryHWMChunk(). Employed by non-hdfs.
void backupHWMChunk (
bool bColumnFile,
OID columnOID,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
HWM lastLocalHwm );
// This function must be thread-safe since it is called directly by
// backupDctnryHWMFile(). Employed by hdfs.
void backupHWMFile (
bool bColumnFile,
OID columnOID,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
HWM lastLocalHwm );
// Close the current meta data file.
EXPORT void closeMetaFile ( );
void createSubDir( const std::string& metaFileName );
void deleteSubDir( const std::string& metaFileName );
int getSubDirPath(const uint16_t dbRoot,
std::string& subDirPath ) const;
// Open a meta data file to save HWM bulk rollback info for tableOID
// Warning: This function may throw a WeException.
// dbRoot is the DBRoot of interest for the applicable table.
std::string openMetaFile ( uint16_t dbRoot );
// Rename temporary metadata control file(s) to the permanent name.
// Filenames are taken from fMetaFileNames.
// Warning: This function may throw a WeException.
void renameMetaFile( );
// Save column meta data to the currently open file.
// This is the Shared-Nothing version of this function.
// Warning: This function may throw a WeException.
// metaFileName name of metafile to be written
// columnOID column OID to be saved
// dbRoot current dbRoot of last local HWM for columnOID
// partition current partition of last local HWM for columnOID
// segment current segment of last local HWM for columnOID
// lastLocalHwm current last local for column OID
// colType type of columnOID
// colTypeName type name of columnOID
// colWidth width (in bytes) of columnOID
// compressionType compression type
void writeColumnMetaData (
const std::string& metaFileName,
bool withHWM,
OID columnOID,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
HWM lastLocalHwm,
execplan::CalpontSystemCatalog::ColDataType colType,
const std::string& colTypeName,
int colWidth,
int compressionType );
// Save dictionary store meta data to the currently open file.
// This is the Shared-Nothing version of this function.
// dictionaryStoreOID dictionary store OID to be saved
// dbRoot dbRoot of store file
// partition partition of store file
// segment segment of store file
// localHwm current local HWM for specified partition and seg file
// compressionType compression type
void writeDictionaryStoreMetaData (
OID columnOID,
OID dictionaryStoreOID,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
HWM localHwm,
int compressionType );
// For first extent stripe in a partition, this function is used to
// to log a marker to denote a trailing segment file that does not exist.
// This is the Shared-Nothing version of this function.
// dictionaryStoreOID dictionary store OID to be saved
// dbRoot dbRoot of store file
// partition partition of store file
// segment segment of store file
// compressionType compression type
void writeDictionaryStoreMetaNoDataMarker (
OID columnOID,
OID dictionaryStoreOID,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
int compressionType );
// This function must be thread-safe since it is called indirectly by
// backupDctnryHWMChunk() (through backupHWMChunk()).
int writeHWMChunk (
bool bColumnFile,
OID columnOID,
uint16_t dbRoot,
uint32_t partition,
uint16_t segment,
const unsigned char* compressedOutBuf,
uint64_t chunkSize,
uint64_t fileSize,
HWM chunkHwm,
std::string& errMsg) const;
void printDctnryChunkList(const RBChunkInfo& rbChk, const char* action);
IDBDataFile* fMetaDataFile; // current meta data file to write
std::ostringstream fMetaDataStream; // adapter for IDBDataFile
std::map<uint16_t, std::string> fMetaFileNames;//map of dbroots to metafiles
std::string fAppDesc; // description of application user
Log* fLog; // import log file
bool fCreatedSubDir; // has subdir path been created
RBChunkSet fRBChunkDctnrySet; // Dctnry HWM chunk info
boost::mutex fRBChunkDctnryMutex;//Mutex lock for RBChunkSet
OID fTableOID; // OID of relevant table
std::string fTableName; // Name of relevant table
};
} //end of namespace
#undef EXPORT
#endif // WE_RBMETAWRITER_H_

View File

@ -0,0 +1,106 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_simplesyslog.cpp 4607 2013-04-11 21:38:09Z rdempsey $
*
*******************************************************************************/
#include "we_simplesyslog.h"
#include "we_define.h"
#include "messagelog.h"
using namespace std;
namespace WriteEngine
{
/*static*/ SimpleSysLog* SimpleSysLog::fSysLogger = 0;
//------------------------------------------------------------------------------
// Singleton instance accessor (Warning, not thread-safe)
//------------------------------------------------------------------------------
/* static */
SimpleSysLog* SimpleSysLog::instance()
{
if ( !fSysLogger )
fSysLogger = new SimpleSysLog();
return fSysLogger;
}
//------------------------------------------------------------------------------
// SimpleSysLog constructor.
//------------------------------------------------------------------------------
SimpleSysLog::SimpleSysLog() : fLoggingID( SUBSYSTEM_ID_WE )
{
}
//------------------------------------------------------------------------------
// Reset LoggingID (in order to set the subsystem id)
//------------------------------------------------------------------------------
void SimpleSysLog::setLoggingID( const logging::LoggingID& loggingID )
{
fLoggingID = loggingID;
}
//------------------------------------------------------------------------------
// Log arguments (msgArgs) for specified msgId to the requested log (logType).
//------------------------------------------------------------------------------
void SimpleSysLog::logMsg( const logging::Message::Args& msgArgs,
logging::LOG_TYPE logType,
logging::Message::MessageID msgId )
{
logging::MessageLog ml( fLoggingID );
logging::Message m(msgId);
m.format(msgArgs);
boost::mutex::scoped_lock lk(fWriteLockMutex);
switch (logType)
{
case logging::LOG_TYPE_DEBUG:
{
ml.logDebugMessage(m);
break;
}
case logging::LOG_TYPE_INFO:
default:
{
ml.logInfoMessage(m);
break;
}
case logging::LOG_TYPE_WARNING:
{
ml.logWarningMessage(m);
break;
}
case logging::LOG_TYPE_ERROR:
{
ml.logErrorMessage(m);
break;
}
case logging::LOG_TYPE_CRITICAL:
{
ml.logCriticalMessage(m);
break;
}
}
}
} //end of namespace

View File

@ -0,0 +1,82 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_simplesyslog.h 4450 2013-01-21 14:13:24Z rdempsey $
*
*******************************************************************************/
/** @file */
#ifndef _WE_SIMPLESYSLOG_H_
#define _WE_SIMPLESYSLOG_H_
#include <boost/thread.hpp>
#include "messagelog.h"
#include "messageobj.h"
#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
/**
* @brief SimpleSysLog class is a simple logger that only logs to syslog.
*
* Note that the instance() and setLoggingID() funtions are not thread-safe.
* They should be called once, upfront by the main thread to perform setup.
*/
class SimpleSysLog
{
public:
/**
* @brief Singleton accessor.
*/
EXPORT static SimpleSysLog* instance();
/**
* @brief Modify the LoggingID to be used. Mainly used to control the
* subsystem ID.
*/
EXPORT void setLoggingID( const logging::LoggingID& loggingID );
/**
* @brief Function that logs a syslog msg.
*/
EXPORT void logMsg( const logging::Message::Args& msgArgs,
logging::LOG_TYPE logType,
logging::Message::MessageID msgId );
private:
SimpleSysLog( );
SimpleSysLog( const SimpleSysLog& );
SimpleSysLog& operator= ( const SimpleSysLog& );
static SimpleSysLog* fSysLogger;
logging::LoggingID fLoggingID;
boost::mutex fWriteLockMutex; // logging mutex
};
#undef EXPORT
} //end of namespace
#endif // _WE_SIMPLESYSLOG_H_

View File

@ -0,0 +1,230 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_stats.cpp 4450 2013-01-21 14:13:24Z rdempsey $
*
*******************************************************************************/
/** @file */
#include <we_stats.h>
using namespace std;
namespace WriteEngine
{
#ifdef PROFILE
/* static */ bool Stats::fProfiling = false;
/* static */ boost::mutex Stats::fRegisterReaderMutex;
/* static */ boost::mutex Stats::fRegisterParseMutex;
/* static */ std::vector<pthread_t> Stats::fReadProfThreads;
/* static */ std::vector<pthread_t> Stats::fParseProfThreads;
/* static */ std::vector<logging::StopWatch> Stats::fReadStopWatch;
/* static */ std::vector<logging::StopWatch> Stats::fParseStopWatch;
#endif
struct IoStats Stats::m_ioStats = { 0, 0 };
bool Stats::m_bUseStats = false;
/***********************************************************
* DESCRIPTION:
* Increase the counter for block read
* PARAMETERS:
* blockNum - the number of blocks
* RETURN:
* none
***********************************************************/
void Stats::incIoBlockRead( const int blockNum )
{
if( !m_bUseStats )
return;
m_ioStats.blockRead += blockNum;
}
/***********************************************************
* DESCRIPTION:
* Increase the counter for block write
* PARAMETERS:
* blockNum - the number of blocks
* RETURN:
* none
***********************************************************/
void Stats::incIoBlockWrite( const int blockNum )
{
if( !m_bUseStats )
return;
m_ioStats.blockWrite += blockNum;
}
#ifdef PROFILE
//-------------------------------------------------------------------------------
// Functions that follow are used for profiling using the StopWatch class
//-------------------------------------------------------------------------------
/***********************************************************
* DESCRIPTION:
* Enable/Initialize the profiling functions
* PARAMETERS:
* nReadThreads - number of read threads to be profiled
* nParseThreads - number of parse threads to be profiled
* RETURN:
* none
***********************************************************/
void Stats::enableProfiling(int nReadThreads, int nParseThreads)
{
fProfiling = true;
// @bug 2625: pre-reserve space for our vectors; else we could have a race
// condition whereby one parsing thread is adding itself to the vectors
// and thus "growing" the vector (in registerParseProfThread), at the
// same time that another parsing thread is reading the vector in parse-
// Event(). By pre-reserving the space, the vectors won't be growing,
// thus eliminating the problem with this race condition.
fReadProfThreads.reserve ( nReadThreads );
fReadStopWatch.reserve ( nReadThreads );
fParseProfThreads.reserve( nParseThreads );
fParseStopWatch.reserve ( nParseThreads );
}
/***********************************************************
* DESCRIPTION:
* Register the current thread as a Read thread to be profiled
* PARAMETERS:
* none
* RETURN:
* none
***********************************************************/
void Stats::registerReadProfThread( )
{
boost::mutex::scoped_lock lk(fRegisterReaderMutex);
fReadProfThreads.push_back( pthread_self() );
logging::StopWatch readStopWatch;
fReadStopWatch.push_back ( readStopWatch );
}
/***********************************************************
* DESCRIPTION:
* Register the current thread as a Parse thread to be profiled
* PARAMETERS:
* none
* RETURN:
* none
***********************************************************/
void Stats::registerParseProfThread( )
{
boost::mutex::scoped_lock lk(fRegisterParseMutex);
fParseProfThreads.push_back( pthread_self() );
logging::StopWatch parseStopWatch;
fParseStopWatch.push_back ( parseStopWatch );
}
/***********************************************************
* DESCRIPTION:
* Track the specified Read event in the current Read thread.
* PARAMETERS:
* eventString - string that identifies the event.
* start - boolean indicating whether the is the start or the
* end of the event. TRUE=>start FALSE=>end
* RETURN:
* none
***********************************************************/
void Stats::readEvent ( const std::string& eventString, bool start )
{
if (fProfiling)
{
pthread_t thread = pthread_self();
for (unsigned i=0; i<fReadProfThreads.size(); i++)
{
if (fReadProfThreads[i] == thread)
{
if (start)
fReadStopWatch[i].start( eventString );
else
fReadStopWatch[i].stop ( eventString );
break;
}
}
}
}
/***********************************************************
* DESCRIPTION:
* Track the specified Parse event in the current Parse thread.
* PARAMETERS:
* eventString - string that identifies the event.
* start - boolean indicating whether the is the start or the
* end of the event. TRUE=>start FALSE=>end
* RETURN:
* none
***********************************************************/
void Stats::parseEvent ( const std::string& eventString, bool start )
{
if (fProfiling)
{
pthread_t thread = pthread_self();
for (unsigned i=0; i<fParseProfThreads.size(); i++)
{
if (fParseProfThreads[i] == thread)
{
if (start)
fParseStopWatch[i].start( eventString );
else
fParseStopWatch[i].stop ( eventString );
break;
}
}
}
}
/***********************************************************
* DESCRIPTION:
* Print profiling results.
* PARAMETERS:
* none
* RETURN:
* none
***********************************************************/
void Stats::printProfilingResults ( )
{
if (fProfiling)
{
std::cout << endl;
for (unsigned j=0; j<fReadStopWatch.size(); j++)
{
std::cout << "Execution Stats for Read Thread " << j << " (" <<
fReadProfThreads[j] << ")" << std::endl <<
"-------------------------------" << std::endl;
fReadStopWatch[j].finish();
std::cout << std::endl;
}
for (unsigned j=0; j<fParseStopWatch.size(); j++)
{
std::cout << "Execution Stats for Parse Thread "<< j << " (" <<
fParseProfThreads[j] << ")" << std::endl <<
"--------------------------------" << std::endl;
fParseStopWatch[j].finish();
std::cout << std::endl;
}
}
}
#endif
} //end of namespace

View File

@ -0,0 +1,163 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/*******************************************************************************
* $Id: we_stats.h 4450 2013-01-21 14:13:24Z rdempsey $
*
*******************************************************************************/
/** @file */
#ifndef _WE_STATS_H_
#define _WE_STATS_H_
#include <we_obj.h>
#ifdef PROFILE
#include <boost/thread/mutex.hpp>
#include "stopwatch.h"
#endif
/** Namespace WriteEngine */
namespace WriteEngine
{
struct IoStats
{
long blockRead;
long blockWrite;
};
/** Class Stats */
class Stats
{
public:
/**
* @brief Constructor
*/
Stats() {}
/**
* @brief Default Destructor
*/
~Stats() {}
/**
* @brief I/O
*/
static long getIoBlockRead() { return m_ioStats.blockRead; }
static long getIoBlockWrite() { return m_ioStats.blockWrite; }
static void incIoBlockRead( const int blockNum = 1 );
static void incIoBlockWrite( const int blockNum = 1 );
static bool getUseStats() { return m_bUseStats; }
static void setUseStats( const bool flag ) { m_bUseStats = flag; }
static IoStats m_ioStats; // IO
#ifdef PROFILE
// Prefined event labels
#define WE_STATS_ALLOC_DCT_EXTENT "AllocDctExtent"
#define WE_STATS_COMPACT_VARBINARY "CompactingVarBinary"
#define WE_STATS_COMPLETING_PARSE "CompletingParse"
#define WE_STATS_COMPLETING_READ "CompletingRead"
#define WE_STATS_COMPRESS_COL_INIT_ABBREV_EXT "CmpColInitAbbrevExtent"
#define WE_STATS_COMPRESS_COL_INIT_BUF "CmpColInitBuf"
#define WE_STATS_COMPRESS_COL_COMPRESS "CmpColCompress"
#define WE_STATS_COMPRESS_COL_FINISH_EXTENT "CmpColFinishExtent"
#define WE_STATS_COMPRESS_DCT_INIT_BUF "CmpDctInitBuf"
#define WE_STATS_COMPRESS_DCT_COMPRESS "CmpDctCompress"
#define WE_STATS_COMPRESS_DCT_SEEKO_CHUNK "CmpDctSeekOutputChunk"
#define WE_STATS_COMPRESS_DCT_WRITE_CHUNK "CmpDctWriteChunk"
#define WE_STATS_COMPRESS_DCT_SEEKO_HDR "CmpDctSeekOutputHdr"
#define WE_STATS_COMPRESS_DCT_WRITE_HDR "CmpDctWriteHdr"
#define WE_STATS_COMPRESS_DCT_BACKUP_CHUNK "CmpDctBackupChunk"
#define WE_STATS_CREATE_COL_EXTENT "CreateColExtent"
#define WE_STATS_CREATE_DCT_EXTENT "CreateDctExtent"
#define WE_STATS_EXPAND_COL_EXTENT "ExpandColExtent"
#define WE_STATS_EXPAND_DCT_EXTENT "ExpandDctExtent"
#define WE_STATS_FLUSH_PRIMPROC_BLOCKS "FlushPrimProcBlocks"
#define WE_STATS_INIT_COL_EXTENT "InitColExtent"
#define WE_STATS_INIT_DCT_EXTENT "InitDctExtent"
#define WE_STATS_OPEN_DCT_FILE "OpenDctFile"
#define WE_STATS_PARSE_COL "ParseCol"
#define WE_STATS_PARSE_DCT "ParseDct"
#define WE_STATS_PARSE_DCT_SEEK_EXTENT_BLK "ParseDctSeekExtentBlk"
#define WE_STATS_READ_INTO_BUF "ReadIntoBuf"
#define WE_STATS_RESIZE_OUT_BUF "ResizeOutBuf"
#define WE_STATS_WAIT_FOR_INTERMEDIATE_FLUSH "WaitForIntermediateFlush"
#define WE_STATS_WAIT_FOR_READ_BUF "WaitForReadBuf"
#define WE_STATS_WAIT_TO_COMPLETE_PARSE "WaitCompleteParse"
#define WE_STATS_WAIT_TO_COMPLETE_READ "WaitCompleteRead"
#define WE_STATS_WAIT_TO_CREATE_COL_EXTENT "WaitCreateColExtent"
#define WE_STATS_WAIT_TO_CREATE_DCT_EXTENT "WaitCreateDctExtent"
#define WE_STATS_WAIT_TO_EXPAND_COL_EXTENT "WaitExpandColExtent"
#define WE_STATS_WAIT_TO_EXPAND_DCT_EXTENT "WaitExpandDctExtent"
#define WE_STATS_WAIT_TO_PARSE_DCT "WaitParseDct"
#define WE_STATS_WAIT_TO_RELEASE_OUT_BUF "WaitReleaseOutBuf"
#define WE_STATS_WAIT_TO_RESERVE_OUT_BUF "WaitReserveOutBuf"
#define WE_STATS_WAIT_TO_RESIZE_OUT_BUF "WaitResizeOutBuf"
#define WE_STATS_WAIT_TO_SELECT_COL "WaitSelectCol"
#define WE_STATS_WAIT_TO_SELECT_TBL "WaitSelectTbl"
#define WE_STATS_WRITE_COL "WriteCol"
#define WE_STATS_WRITE_DCT "WriteDct"
// Functions used to support performance profiling
static void enableProfiling(int nReadThreads, int nParseThreads);
static void registerReadProfThread ( );
static void registerParseProfThread( );
static void startReadEvent ( const std::string& eventString )
{ readEvent ( eventString, true ); }
static void stopReadEvent ( const std::string& eventString )
{ readEvent ( eventString, false ); }
static void startParseEvent( const std::string& eventString )
{ parseEvent( eventString, true ); }
static void stopParseEvent ( const std::string& eventString )
{ parseEvent( eventString, false ); }
static void printProfilingResults( );
#endif
private:
static bool m_bUseStats; // Use statistic flag
#ifdef PROFILE
// Data members and functions used to support performance profiling
static bool fProfiling; // Is profiling enabled
// Protect concurrent addition of Readers
static boost::mutex fRegisterReaderMutex;
// Protect concurrent addition of Parsers
static boost::mutex fRegisterParseMutex;
// Read threads to be profiled
static std::vector<pthread_t> fReadProfThreads;
// Parse threads to be profiled
static std::vector<pthread_t> fParseProfThreads;
// Track/profile Read events
static std::vector<logging::StopWatch> fReadStopWatch;
// Track/profile Parse events
static std::vector<logging::StopWatch> fParseStopWatch;
static void readEvent ( const std::string& eventString, bool start );
static void parseEvent ( const std::string& eventString, bool start );
#endif
};
} //end of namespace
#endif // _WE_STATIS_H_

View File

@ -0,0 +1,473 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id: we_type.h 4737 2013-08-14 20:45:46Z bwilkinson $
/** @file */
#ifndef _WE_TYPE_H_
#define _WE_TYPE_H_
#undef EXPORT
#undef DELETE
#undef NO_ERROR
#include <sys/types.h>
#include <string>
#include <vector>
#include <boost/any.hpp>
#include <cstring>
#include <stdexcept>
#include "we_define.h"
#include "we_typeext.h"
#include "calpontsystemcatalog.h"
#include "IDBDataFile.h"
#include "IDBPolicy.h"
#undef EXPORT
#undef DELETE
#undef NO_ERROR
/** Namespace WriteEngine */
namespace WriteEngine
{
typedef idbdatafile::IDBDataFile IDBDataFile;
/************************************************************************
* Type definitions
************************************************************************/
typedef uint32_t OID; /** @brief Object ID */
typedef uint32_t FID; /** @brief File ID */
typedef uint64_t RID; /** @brief Row ID */
typedef uint32_t TxnID; /** @brief Transaction ID (New)*/
typedef uint32_t HWM; /** @brief high water mark */
/************************************************************************
* Type enumerations
************************************************************************/
enum DebugLevel { /** @brief Debug level type */
DEBUG_0 = 0, /** @brief No debug info */
DEBUG_1 = 1, /** @brief Summary level debug */
DEBUG_2 = 2, /** @brief Moderate debug */
DEBUG_3 = 3, /** @brief Detail debug */
};
// INFO2 only goes to log file unless '-i' cmd line arg is specified,
// in which case the msg will also get logged to the console.
// All other messages always get logged to the log file and the console.
enum MsgLevel { /** @brief Message level */
MSGLVL_INFO1 = 0, /** @brief Basic Information level*/
MSGLVL_INFO2 = 1, /** @brief More Information level */
MSGLVL_WARNING = 2, /** @brief Warning level */
MSGLVL_ERROR = 3, /** @brief Error level */
MSGLVL_CRITICAL = 4, /** @brief Critical level */
};
enum OpType { /** @brief Operation type */
NOOP = 0, /** @brief No oper */
INSERT = 1, /** @brief Insert */
UPDATE = 2, /** @brief Update */
DELETE = 4, /** @brief Delete */
QUERY = 8, /** @brief Query */
};
enum ColType { /** @brief Column type enumeration*/
// WR_BIT = 1, /** @brief Bit */
WR_BYTE = 2, /** @brief Byte */
WR_SHORT = 3, /** @brief Short */
WR_INT = 4, /** @brief Int */
// WR_LONG = 5, /** @brief Long */
WR_LONGLONG = 6, /** @brief Long long*/
WR_FLOAT = 7, /** @brief Float */
WR_DOUBLE = 8, /** @brief Double */
WR_CHAR = 9, /** @brief Char */
WR_TOKEN = 10, /** @brief Token */
WR_BLOB = 11, /** @brief BLOB */
WR_VARBINARY = 12, /** @brief VARBINARY */
WR_UBYTE = 13, /** @brief Unsigned Byte */
WR_USHORT = 14, /** @brief Unsigned Short */
WR_UINT = 15, /** @brief Unsigned Int */
WR_ULONGLONG = 16, /** @brief Unsigned Long long*/
};
// Describes relation of field to column for a bulk load
enum BulkFldColRel { BULK_FLDCOL_COLUMN_FIELD, // map input field to db col
BULK_FLDCOL_COLUMN_DEFAULT,// import def val to db col
BULK_FLDCOL_IGNORE_FIELD };// ignore fld in import file
// Bulk Load Mode (ex: local vs remote, single src vs multiple src files)
enum BulkModeType { BULK_MODE_REMOTE_SINGLE_SRC = 1,
BULK_MODE_REMOTE_MULTIPLE_SRC = 2,
BULK_MODE_LOCAL = 3 };
// Import Mode 0-text Import (default)
// 1-Binary Import with NULL values
// 2-Binary Import with saturated NULL values
enum ImportDataMode { IMPORT_DATA_TEXT = 0,
IMPORT_DATA_BIN_ACCEPT_NULL = 1,
IMPORT_DATA_BIN_SAT_NULL = 2 };
/**
* the set of Calpont column data type names; MUST match ColDataType in
* calpontsystemcatalog.h.
*/
const char ColDataTypeStr[execplan::CalpontSystemCatalog::NUM_OF_COL_DATA_TYPE][20] = {
"bit",
"tinyint",
"char",
"smallint",
"decimal",
"medint",
"integer",
"float",
"date",
"bigint",
"double",
"datetime",
"varchar",
"varbinary",
"clob",
"blob",
"unsigned-tinyint",
"unsigned-smallint",
"unsigned-decimal",
"unsigned-med int",
"unsigned-int",
"unsigned-float",
"unsigned-bigint",
"unsigned-double"
};
enum FuncType { FUNC_WRITE_ENGINE, FUNC_INDEX, FUNC_DICTIONARY };
enum CacheListType { FREE_LIST, LRU_LIST, WRITE_LIST }; /** @brief List type */
/************************************************************************
* struct data block structure
************************************************************************/
struct DataBlock /** @brief Data block structure */
{
long no; /** @brief block number */
uint64_t lbid; /** @brief lbid */
bool dirty; /** @brief block dirty flag */
int state; /** @brief initialized 0, read 1 , modified 2 */
unsigned char data[BYTE_PER_BLOCK];/** @brief data buffer */
DataBlock() { dirty = false; /** @brief constructor */
memset( data, 0, BYTE_PER_BLOCK ); }
};
struct DataSubBlock /** @brief Data subblock structure*/
{
long no; /** @brief sub block number */
bool dirty; /** @brief block dirty flag */
unsigned char data[BYTE_PER_SUBBLOCK]; /** @brief data buffer */
DataSubBlock() { dirty = false; memset( data, 0, BYTE_PER_SUBBLOCK ); } /** @brief constructor */
};
/************************************************************************
* @brief file structure. Default copy constructor, assignment oper, etc
* are in play here, as they are not overridden. Beware that if copies
* of a File object are made, only one user should be closing the pFile.
* oid and fid replicate one another. oid mostly used by index, cache,
* and dictionary. fid mostly used by colop and bulk.
************************************************************************/
struct File /** @brief File structure */
{
OID oid; /** @brief Oid */
FID fid; /** @brief File id */
HWM hwm; /** @brief High water mark */
IDBDataFile* pFile; /** @brief File handle */
uint32_t fPartition; /** @brief Partition for pFile*/
uint16_t fSegment; /** @brief Segment for pFile */
uint16_t fDbRoot; /** @brief DbRoot for pFile */
std::string fSegFileName; /** @brief Current seg file path */
File() { clear(); } /** @brief constructor */
void clear() { pFile = NULL; oid = fid = hwm = 0;
fPartition = fSegment = fDbRoot = 0;
fSegFileName.clear(); }
};
/************************************************************************
* @brief Internal communication block structure
************************************************************************/
struct CommBlock /** @brief Communication Block */
{
File file; /** @brief File structure */
void clear() { file.clear(); }
};
/************************************************************************
* @brief column structure used to pass data in/out of we_colop functions
************************************************************************/
struct Column /** @brief Column structure */
{
int colNo; /** @brief column number */
int colWidth; /** @brief column width */
ColType colType; /** @brief column type (internal use)*/
execplan::CalpontSystemCatalog::ColDataType colDataType; /** @brief column data type (from interface)*/
File dataFile; /** @brief column data file */
int compressionType; /** @brief column compression type*/
Column() : colNo(0), colWidth(0), colType(WR_INT),
colDataType(execplan::CalpontSystemCatalog::INT),
compressionType(idbdatafile::IDBPolicy::useHdfs()?2:0) { }
};
/************************************************************************
* @brief dictionary related structures (Token struct is defined in
* we_typeext.h to facilitate its use in dbcon and utils/dataconvert).
************************************************************************/
typedef struct offset_ /** @brief Offset structure */
{
int hdrLoc; /** @brief offset postion in hdr */
uint16_t offset; /** @brief offset in block */
} Offset;
/************************************************************************
* @brief interfaces with DDL/DML
************************************************************************/
typedef struct colTuple_struct /** @brief Column Tuple definition*/
{
boost::any data; /** @brief column value */
} ColTuple;
typedef std::vector<ColTuple> ColTupleList; /** @brief column value list */
struct ColStruct /** @brief Column Interface Struct*/
{
OID dataOid; /** @brief column data file object id */
int colWidth; /** @brief column width */
bool tokenFlag; /** @brief column token flag, must be set to true if it is a token column */
execplan::CalpontSystemCatalog::ColDataType colDataType; /** @brief column data type (for interface)*/
ColType colType; /** @brief column type (internal use for write engine)*/
uint32_t fColPartition; /** @brief Partition for column file */
uint16_t fColSegment; /** @brief Segment for column file*/
uint16_t fColDbRoot; /** @brief DBRoot for column file */
int fCompressionType; /** @brief Compression tpye for column file */
ColStruct() : dataOid(0), colWidth(0), /** @brief constructor */
tokenFlag(false), colDataType(execplan::CalpontSystemCatalog::INT), colType(WR_INT),
fColPartition(0), fColSegment(0), fColDbRoot(0),
fCompressionType(idbdatafile::IDBPolicy::useHdfs()?2:0) { }
};
typedef std::vector<ColStruct> ColStructList; /** @brief column struct list */
typedef std::vector<ColTupleList> ColValueList; /** @brief column value list */
typedef std::vector<RID> RIDList; /** @brief RID list */
typedef std::vector<std::string> dictStr;
typedef std::vector<dictStr> DictStrList;
// dictionary
struct DctnryStruct /** @brief Dctnry Interface Struct*/
{
OID dctnryOid; /** @brief dictionary signature file */
OID columnOid; /** @brief corresponding column file */
int colWidth; /** @brief string width for the dictionary column*/
uint32_t fColPartition; /** @brief Partition for column file */
uint16_t fColSegment; /** @brief Segment for column file */
uint16_t fColDbRoot; /** @brief DBRoot for column file */
int fCompressionType; /** @brief Compression tpye for column file */
DctnryStruct() : dctnryOid(0), columnOid(0), /** @brief constructor */
colWidth(0),
fColPartition(0), fColSegment(0),
fColDbRoot(0), fCompressionType(idbdatafile::IDBPolicy::useHdfs()?2:0) { }
};
struct DctnryTuple /** @brief Dictionary Tuple struct*/
{
unsigned char sigValue[MAX_SIGNATURE_SIZE]; /** @brief dictionary signature value*/
int sigSize; /** @brief dictionary signature size */
Token token; /** @brief dictionary token */
bool isNull;
DctnryTuple() { }
~DctnryTuple() { }
};
typedef std::vector<DctnryTuple> DctColTupleList;
typedef std::vector<DctnryStruct> DctnryStructList; /** @brief column struct list */
typedef std::vector<DctColTupleList> DctnryValueList; /** @brief column value list */
/************************************************************************
* @brief Used by Bulk Load to describe a column
************************************************************************/
struct JobColumn /** @brief Job Column Structure */
{
std::string colName; /** @brief column name */
OID mapOid; /** @brief column OID */
execplan::CalpontSystemCatalog::ColDataType dataType; /** @brief column data type */
ColType weType; /** @brief write engine data type */
std::string typeName; /** @brief data type name */
uint64_t emptyVal; /** @brief default empty value */
int width; /** @brief column width; for a dictionary column, this is "eventually" the token width */
int definedWidth; /** @brief column width as defined in the table, used for non-dictionary strings */
int dctnryWidth; /** @brief dictionary width */
int precision; /** @brief precision of decimal */
int scale; /** @brief scale of decimal */
bool fNotNull; /** @brief not null flag */
BulkFldColRel fFldColRelation; /** @brief type of field/col relation*/
char colType; /** @brief column type, blank is regular, D is dictionary */
int compressionType; /** @brief compression type */
bool autoIncFlag; /** @brief auto increment flag */
DctnryStruct dctnry; /** @brief dictionary structure */
int64_t fMinIntSat; /** @brief For integer type, the min saturation value */
uint64_t fMaxIntSat; /** @brief For integer type, the max saturation value */
double fMinDblSat; /** @brief for float/double, the min saturation value */
double fMaxDblSat; /** @brief for float/double, the max saturation value */
bool fWithDefault; /** @brief With default */
long long fDefaultInt; /** @brief Integer column default */
unsigned long long fDefaultUInt; /** @brief UnsignedInt col default*/
double fDefaultDbl; /** @brief Dbl/Flt column default */
std::string fDefaultChr; /** @brief Char column default */
JobColumn() : mapOid(0), dataType(execplan::CalpontSystemCatalog::INT), weType(WR_INT),
typeName("integer"), emptyVal(0),
width(0), definedWidth(0), dctnryWidth(0),
precision(0), scale(0), fNotNull(false),
fFldColRelation(BULK_FLDCOL_COLUMN_FIELD), colType(' '),
compressionType(0),autoIncFlag(false),
fMinIntSat(0), fMaxIntSat(0),
fMinDblSat(0), fMaxDblSat(0), fWithDefault(false),
fDefaultInt(0), fDefaultUInt(0), fDefaultDbl(0.0)
{ }
};
typedef std::vector<JobColumn> JobColList; /** @brief column value list */
struct JobFieldRef // references field/column in JobTable
{
BulkFldColRel fFldColType; // type of field or column
unsigned fArrayIndex; // index into colList or fIgnoredFields
// in JobTable based on fFldColType.
JobFieldRef( ) : fFldColType(BULK_FLDCOL_COLUMN_FIELD), fArrayIndex(0) { }
JobFieldRef( BulkFldColRel fldColType, unsigned idx ) :
fFldColType( fldColType ), fArrayIndex( idx ) { }
};
typedef std::vector<JobFieldRef> JobFieldRefList;
struct JobTable /** @brief Job Table Structure */
{
std::string tblName; /** @brief table name */
OID mapOid; /** @brief table OID */
std::string loadFileName; /** @brief table load file name */
uint64_t maxErrNum; /** @brief max number of error rows before abort */
JobColList colList; /** @brief list of columns to be loaded; followed by default columns to be loaded */
JobColList fIgnoredFields; /** @brief list of fields in input file to be ignored */
JobFieldRefList fFldRefs; /** @brief Combined list of refs to entries in colList and fIgnoredFields */
JobTable() : mapOid(0), maxErrNum(0) { }
};
typedef std::vector<JobTable> JobTableList;/** @brief table list */
struct Job /** @brief Job Structure */
{
int id; /** @brief job id */
std::string schema; /** @brief database name */
std::string name; /** @brief job name */
std::string desc; /** @brief job description */
std::string userName; /** @brief user name */
JobTableList jobTableList; /** @brief job table list */
std::string createDate; /** @brief job create date */
std::string createTime; /** @brief job create time */
char fDelimiter;
char fEnclosedByChar;
char fEscapeChar;
int numberOfReadBuffers;
unsigned readBufferSize;
unsigned writeBufferSize;
Job() : id(0), fDelimiter('|'),
fEnclosedByChar('\0'), fEscapeChar('\0'),
numberOfReadBuffers(0), readBufferSize(0), writeBufferSize(0) { }
};
/************************************************************************
* @brief Cache memory
************************************************************************/
struct CacheBlock /** @brief Cache block structure */
{
uint64_t fbo; /** @brief file fbo */
uint64_t lbid; /** @brief lbid */
bool dirty; /** @brief dirty flag */
int hitCount; /** @brief hit count */
unsigned char* data; /** @brief block buffer */
CacheBlock() { data = NULL; clear(); }/** @brief constructor */
void clear() { fbo = lbid = hitCount = 0;
dirty = false;
if( data ) memset( data, 0, BYTE_PER_BLOCK); } /** @brief clear, NOTE: buf must be free by caller first */
void init() { data = (unsigned char*)malloc(BYTE_PER_BLOCK); }
void freeMem() { if( data ) free( data ); }
};
struct BlockBuffer /** @brief Block buffer */
{
CommBlock cb; /** @brief Communication block structure */
CacheBlock block; /** @brief Cache block strucutre */
CacheListType listType; /** @brief List number, 0 - free, 1 - LRU, 2 - write */
BlockBuffer() { clear(); } /** @brief constructor */
void init() { block.init(); }
void freeMem() { block.freeMem(); }
void clear() { cb.clear(); block.clear(); listType = FREE_LIST; }
};
struct CacheControl /** @brief Cache control structure */
{
int totalBlock; /** @brief The toal number of allocated blocks */
int pctFree; /** @brief The percentage of free blocks when some blocks must be aged out */
int checkInterval; /** @brief A check point interval in seconds */
CacheControl() { totalBlock = pctFree = checkInterval; } /** @brief constructor */
};
/************************************************************************
* @brief Bulk parse meta data describing data in a read buffer.
* An offset of COLPOSPAIR_NULL_TOKEN_OFFSET represents a null token.
************************************************************************/
struct ColPosPair /** @brief Column position pair structure */
{
int start; /** @brief start position */
int offset; /** @brief length of token*/
};
/************************************************************************
* @brief SecondaryShutdown used to terminate a thread when it sees that the
* JobStatus flag has been set to EXIT_FAILURE (by another thread).
************************************************************************/
class SecondaryShutdownException : public std::runtime_error
{
public:
SecondaryShutdownException(const std::string& msg) :
std::runtime_error(msg) { }
};
/************************************************************************
* @brief Generic exception class used to store exception string and error
* code for a writeengine error.
************************************************************************/
class WeException : public std::runtime_error
{
public:
WeException(const std::string& msg, int err=0) :
std::runtime_error(msg), fErrorCode(err) { }
void errorCode(int code) { fErrorCode = code; }
int errorCode() const { return fErrorCode; }
private:
int fErrorCode;
};
} //end of namespace
#endif // _WE_TYPE_H_

View File

@ -0,0 +1,60 @@
/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
// $Id$
/** @file
*
* File contains basic typedefs shared externally with other parts of the
* system. These types are placed here rather than in we_type.h in order
* to decouple we_type.h and we_define.h from external components, so that
* the other libraries won't have to recompile every time we change something
* in we_type.h and/or we_define.h.
*/
#ifndef _WE_TYPEEXT_H_
#define _WE_TYPEEXT_H_
#include <stdint.h>
#include <sys/types.h>
/** Namespace WriteEngine */
namespace WriteEngine
{
/************************************************************************
* Type definitions
************************************************************************/
typedef uint64_t RID; // Row ID
/************************************************************************
* Dictionary related structure
************************************************************************/
struct Token {
uint64_t op : 10; // ordinal position within a block
uint64_t fbo : 36; // file block number
uint64_t spare : 18; // spare
Token() // constructor, set to null value
{
op = 0x3FE;
fbo = 0xFFFFFFFFFLL;
spare = 0x3FFFF;
}
};
} //end of namespace
#endif // _WE_TYPEEXT_H_