Merge pull request #57 from tmakatos/v0.7-devel-static
Allow 3rd party emitters to be statically compiled
This commit is contained in:
		
							
								
								
									
										18
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								Makefile.in
									
									
									
									
									
								
							| @@ -92,7 +92,6 @@ SOURCE=\ | ||||
| 	thin-provisioning/restore_emitter.cc \ | ||||
| 	thin-provisioning/rmap_visitor.cc \ | ||||
| 	thin-provisioning/superblock.cc \ | ||||
| 	thin-provisioning/shared_library_emitter.cc \ | ||||
| 	thin-provisioning/thin_check.cc \ | ||||
| 	thin-provisioning/thin_delta.cc \ | ||||
| 	thin-provisioning/thin_dump.cc \ | ||||
| @@ -119,10 +118,23 @@ ifeq ("@DEVTOOLS@", "yes") | ||||
| SOURCE+=$(DEVTOOLS_SOURCE) | ||||
| endif | ||||
|  | ||||
| ifeq ("@STATIC@", "yes") | ||||
| SOURCE += thin-provisioning/static_library_emitter.cc | ||||
| else | ||||
| SOURCE += thin-provisioning/shared_library_emitter.cc | ||||
| endif | ||||
|  | ||||
| CC:=@CC@ | ||||
| CXX:=@CXX@ | ||||
| STRIP:=@STRIP@ | ||||
| OBJECTS:=$(subst .cc,.o,$(SOURCE)) | ||||
|  | ||||
| # FIXME OBJECTS += $(PLUGIN_LIBS) doesn't work, probably because it's empty at | ||||
| # the time of use? | ||||
| ifeq ("@STATIC@", "yes") | ||||
| OBJECTS += contrib/*.a | ||||
| endif | ||||
|  | ||||
| TOP_DIR:=@top_srcdir@ | ||||
| TOP_BUILDDIR:=@top_builddir@ | ||||
| CFLAGS+=-g -Wall -O3 -fPIC | ||||
| @@ -150,6 +162,10 @@ else | ||||
| CXXLIB+=-lstdc++ | ||||
| endif | ||||
|  | ||||
| ifeq ("@STATIC@", "yes") | ||||
| LDFLAGS+=-static | ||||
| endif | ||||
|  | ||||
| INSTALL:=@INSTALL@ | ||||
| PREFIX:=@prefix@ | ||||
| BINDIR:=$(DESTDIR)$(PREFIX)/sbin | ||||
|   | ||||
| @@ -153,6 +153,14 @@ AC_ARG_ENABLE(static_cxx, | ||||
|               STATIC_CXX=$enableval, STATIC_CXX=no) | ||||
| AC_MSG_RESULT($STATIC_CXX) | ||||
|  | ||||
| ################################################################################ | ||||
| dnl -- Enable static linking. | ||||
| AC_MSG_CHECKING(whether to statically link) | ||||
| AC_ARG_ENABLE(static, | ||||
|               AC_HELP_STRING(--enable-static, [enable static link]), | ||||
|               STATIC=$enableval, STATIC=no) | ||||
| AC_MSG_RESULT($STATIC) | ||||
|  | ||||
| ################################################################################ | ||||
| dnl -- Check for getopt | ||||
| AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getopt_long is available.])) | ||||
| @@ -182,6 +190,7 @@ AC_SUBST(TESTING) | ||||
| AC_SUBST(THIN_PROVISIONING_TOOLS_VERSION) | ||||
| AC_SUBST(STATIC_CXX) | ||||
| AC_SUBST(DEVTOOLS) | ||||
| AC_SUBST(STATIC) | ||||
|  | ||||
| ################################################################################ | ||||
| dnl -- First and last lines should not contain files to generate in order to | ||||
|   | ||||
| @@ -1,20 +1,24 @@ | ||||
| PLUGIN_LIBS= \ | ||||
| 	contrib/thin_sexp_emitter.a \ | ||||
| 	contrib/tmakatos_emitter.a \ | ||||
| 	contrib/ewheeler_emitter.a | ||||
|  | ||||
| PLUGINS=\ | ||||
| 	contrib/thin_sexp_emitter.so \ | ||||
| 	contrib/tmakatos_emitter.so \ | ||||
| 	contrib/ewheeler_emitter.so | ||||
|  | ||||
| contrib: $(PLUGINS) | ||||
| contrib: $(PLUGINS) $(PLUGIN_LIBS) | ||||
|  | ||||
| contrib/thin_sexp_emitter.so: contrib/thin_sexp_emitter.o | ||||
| contrib/%.o: contrib/%.cc | ||||
| 	$(V)echo "    [CC] $@" | ||||
| 	$(V)$(CC) $^ -o $@ | ||||
|  | ||||
| contrib/%.a: contrib/%.o | ||||
| 	$(V)echo "    [AR] $@" | ||||
| 	$(V)ar rcs $@ $^ | ||||
|  | ||||
| contrib/%.so: contrib/%.a | ||||
| 	$(V)echo "    [LD] $@" | ||||
| 	$(V)$(CC) -shared -Wl,-soname,thin_sexp_emitter.so -o $@ $< | ||||
|  | ||||
| contrib/tmakatos_emitter.so: contrib/tmakatos_emitter.o | ||||
| 	$(V)echo "    [LD] $@" | ||||
| 	$(V)$(CC) -shared -Wl,-soname,tmakatos_emitter.so -o $@ $< | ||||
|  | ||||
| contrib/ewheeler_emitter.so: contrib/ewheeler_emitter.o | ||||
| 	$(V)echo "    [LD] $@" | ||||
| 	$(V)$(CC) -shared -Wl,-soname,ewheeler_emitter.so -o $@ $< | ||||
|  | ||||
| 	$(V)$(CC) -shared -Wl,-soname,$@ -o $@ $< | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| #include "thin-provisioning/emitter.h" | ||||
| #include "contrib/tmakatos_emitter.h" | ||||
|  | ||||
| #include <iostream> | ||||
| #include <climits> | ||||
| @@ -8,7 +9,7 @@ using namespace thin_provisioning; | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| namespace { | ||||
| namespace tmakatos_emitter { | ||||
| 	template <typename T> | ||||
| 	std::ostream &operator << (ostream &out, boost::optional<T> const &maybe) { | ||||
| 		if (maybe) | ||||
| @@ -20,131 +21,108 @@ namespace { | ||||
| 	//------------------------------------------------ | ||||
| 	// binary generator | ||||
| 	//------------------------------------------------ | ||||
| 	class binary_emitter : public emitter { | ||||
| 	public: | ||||
| 		binary_emitter(ostream &out) | ||||
| 		: out_(out) { | ||||
| 		} | ||||
| 	binary_emitter::binary_emitter(ostream &out): out_(out) { | ||||
| 	} | ||||
|  | ||||
| 		void begin_superblock(string const &uuid, | ||||
| 				      uint64_t time, | ||||
| 				      uint64_t trans_id, | ||||
| 				      boost::optional<uint32_t> flags, | ||||
| 				      boost::optional<uint32_t> version, | ||||
| 				      uint32_t data_block_size, | ||||
| 				      uint64_t nr_data_blocks, | ||||
| 				      boost::optional<uint64_t> metadata_snap) { | ||||
| 		} | ||||
| 	void binary_emitter::begin_superblock(string const &uuid, | ||||
| 			      uint64_t time, | ||||
| 			      uint64_t trans_id, | ||||
| 			      boost::optional<uint32_t> flags, | ||||
| 			      boost::optional<uint32_t> version, | ||||
| 			      uint32_t data_block_size, | ||||
| 			      uint64_t nr_data_blocks, | ||||
| 			      boost::optional<uint64_t> metadata_snap) { | ||||
| 	} | ||||
|  | ||||
| 		void end_superblock() { | ||||
| 		} | ||||
| 	void binary_emitter::end_superblock() { | ||||
| 	} | ||||
|  | ||||
| 		void begin_device(uint32_t dev_id, | ||||
| 				  uint64_t mapped_blocks, | ||||
| 				  uint64_t trans_id, | ||||
| 				  uint64_t creation_time, | ||||
| 				  uint64_t snap_time) { | ||||
| 			cur = 0; | ||||
| 			bitmap = 0; | ||||
| 		} | ||||
| 	void binary_emitter::begin_device(uint32_t dev_id, | ||||
| 			  uint64_t mapped_blocks, | ||||
| 			  uint64_t trans_id, | ||||
| 			  uint64_t creation_time, | ||||
| 			  uint64_t snap_time) { | ||||
| 		cur = 0; | ||||
| 		bitmap = 0; | ||||
| 	} | ||||
|  | ||||
| 		void end_device() { | ||||
| 			emit_bmp(true); | ||||
| 		} | ||||
| 	void binary_emitter::end_device() { | ||||
| 		emit_bmp(true); | ||||
| 	} | ||||
|  | ||||
| 		void begin_named_mapping(string const &name) { } | ||||
| 	void binary_emitter::begin_named_mapping(string const &name) { } | ||||
|  | ||||
| 		void end_named_mapping() { } | ||||
| 	void binary_emitter::end_named_mapping() { } | ||||
|  | ||||
| 		void identifier(string const &name) { } | ||||
| 		void range_map(uint64_t origin_begin, uint64_t, uint32_t, | ||||
| 			       uint64_t len) { | ||||
| 	void binary_emitter::identifier(string const &name) { } | ||||
|  | ||||
| 			uint64_t n = origin_begin / unit; | ||||
| 			uint64_t i; | ||||
| 	void binary_emitter::range_map(uint64_t origin_begin, uint64_t, uint32_t, | ||||
| 		       uint64_t len) { | ||||
|  | ||||
| 			assert(n >= cur); | ||||
| 			assert(len > 0); | ||||
| 		uint64_t n = origin_begin / unit; | ||||
| 		uint64_t i; | ||||
|  | ||||
| 			/* | ||||
| 			 * Cover the gap between the last emitted unit and the current one. | ||||
| 			 */ | ||||
| 			if (n > cur) | ||||
| 				do { emit_bmp(); } while (cur < n); | ||||
|  | ||||
| 			/* | ||||
| 			 * Emit partial unit. | ||||
| 			 */ | ||||
| 			if (origin_begin & (unit - 1)) { | ||||
| 				const uint64_t j = min(len, | ||||
| 						       (origin_begin & ~(unit - 1)) + unit - origin_begin); | ||||
| 				for (i = origin_begin; i < origin_begin + j; i++) | ||||
| 					bitmap |= 1ULL << (i & (unit - 1)); | ||||
| 				if (j == len) | ||||
| 					return; | ||||
|  | ||||
| 				emit_bmp(); | ||||
|  | ||||
| 				len -= j; | ||||
| 				origin_begin = i; | ||||
| 			} | ||||
|  | ||||
| 			/* | ||||
| 			 * Emit full units until end. | ||||
| 			 */ | ||||
| 			n = (origin_begin + len) / unit; | ||||
| 			while (cur < n) { | ||||
| 				bitmap = ~0; | ||||
| 				emit_bmp(); | ||||
| 				len -= unit; | ||||
| 			} | ||||
| 			origin_begin = cur * unit; | ||||
|  | ||||
| 			/* | ||||
| 			 * Emit final unit. | ||||
| 			 */ | ||||
| 			for (i = origin_begin; i < origin_begin + len; i++) | ||||
| 				bitmap |= 1ULL << (i & (unit - 1)); | ||||
| 		} | ||||
|  | ||||
| 		void single_map(uint64_t origin_block, uint64_t, uint32_t) { | ||||
| 			range_map(origin_block, 0, 0, 1); | ||||
| 		} | ||||
|  | ||||
| 	private: | ||||
| 		ostream &out_; | ||||
|  | ||||
| 		/** | ||||
| 		 * The entire virtual block allocation bitmap is segmented into 64-bit | ||||
| 		 * sub-bitmaps (units). | ||||
| 		 */ | ||||
| 		uint64_t bitmap; | ||||
| 		assert(n >= cur); | ||||
| 		assert(len > 0); | ||||
|  | ||||
| 		/* | ||||
| 		 * Pointer to the current sub-bitmap (unit) that has not yet been | ||||
| 		 * emitted. | ||||
| 		 * Cover the gap between the last emitted unit and the current one. | ||||
| 		 */ | ||||
| 		uint64_t cur; | ||||
| 		if (n > cur) | ||||
| 			do { emit_bmp(); } while (cur < n); | ||||
|  | ||||
| 		/** | ||||
| 		 * Unit (sub-bitmap) size. Must be a power of 2. | ||||
| 		/* | ||||
| 		 * Emit partial unit. | ||||
| 		 */ | ||||
| 		static const size_t unit = sizeof bitmap * CHAR_BIT; | ||||
| 		if (origin_begin & (unit - 1)) { | ||||
| 			const uint64_t j = min(len, | ||||
| 					       (origin_begin & ~(unit - 1)) + unit - origin_begin); | ||||
| 			for (i = origin_begin; i < origin_begin + j; i++) | ||||
| 				bitmap |= 1ULL << (i & (unit - 1)); | ||||
| 			if (j == len) | ||||
| 				return; | ||||
|  | ||||
| 		void emit_bmp(bool omit_if_zero = false) { | ||||
| 			if (!bitmap && omit_if_zero) | ||||
| 				out_.write((const char*)&bitmap, sizeof bitmap); | ||||
| 			bitmap = 0; | ||||
| 			cur++; | ||||
| 			emit_bmp(); | ||||
|  | ||||
| 			len -= j; | ||||
| 			origin_begin = i; | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 		/* | ||||
| 		 * Emit full units until end. | ||||
| 		 */ | ||||
| 		n = (origin_begin + len) / unit; | ||||
| 		while (cur < n) { | ||||
| 			bitmap = ~0; | ||||
| 			emit_bmp(); | ||||
| 			len -= unit; | ||||
| 		} | ||||
| 		origin_begin = cur * unit; | ||||
|  | ||||
| 		/* | ||||
| 		 * Emit final unit. | ||||
| 		 */ | ||||
| 		for (i = origin_begin; i < origin_begin + len; i++) | ||||
| 			bitmap |= 1ULL << (i & (unit - 1)); | ||||
| 	} | ||||
|  | ||||
| 	void binary_emitter::single_map(uint64_t origin_block, uint64_t, uint32_t) { | ||||
| 		range_map(origin_block, 0, 0, 1); | ||||
| 	} | ||||
|  | ||||
| 	void binary_emitter::emit_bmp(bool omit_if_zero) { | ||||
| 		if (bitmap || !omit_if_zero) | ||||
| 			out_.write((const char*)&bitmap, sizeof bitmap); | ||||
| 		bitmap = 0; | ||||
| 		cur++; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| extern "C" { | ||||
| 	emitter::ptr create_emitter(ostream &out) { | ||||
| 		return emitter::ptr(new binary_emitter(out)); | ||||
| 		return emitter::ptr(new tmakatos_emitter::binary_emitter(out)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										69
									
								
								contrib/tmakatos_emitter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								contrib/tmakatos_emitter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| #ifndef _TMAKATOS_EMITTER_H_ | ||||
| #define _TMAKATOS_EMITTER_H_ | ||||
|  | ||||
| #include "thin-provisioning/emitter.h" | ||||
| #include <climits> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace thin_provisioning; | ||||
|  | ||||
| namespace tmakatos_emitter { | ||||
| 	class binary_emitter : public emitter { | ||||
| 	public: | ||||
| 		binary_emitter(ostream &out); | ||||
|  | ||||
| 		void begin_superblock(string const &uuid, | ||||
| 				      uint64_t time, | ||||
| 				      uint64_t trans_id, | ||||
| 				      boost::optional<uint32_t> flags, | ||||
| 				      boost::optional<uint32_t> version, | ||||
| 				      uint32_t data_block_size, | ||||
| 				      uint64_t nr_data_blocks, | ||||
| 				      boost::optional<uint64_t> metadata_snap); | ||||
|  | ||||
| 		void end_superblock(); | ||||
|  | ||||
| 		void begin_device(uint32_t dev_id, | ||||
| 				  uint64_t mapped_blocks, | ||||
| 				  uint64_t trans_id, | ||||
| 				  uint64_t creation_time, | ||||
| 				  uint64_t snap_time); | ||||
|  | ||||
| 		void end_device(); | ||||
|  | ||||
| 		void begin_named_mapping(string const &name); | ||||
|  | ||||
| 		void end_named_mapping(); | ||||
|  | ||||
| 		void identifier(string const &name); | ||||
|  | ||||
| 		void range_map(uint64_t origin_begin, uint64_t, uint32_t, | ||||
| 			       uint64_t len); | ||||
|  | ||||
| 		void single_map(uint64_t origin_block, uint64_t, uint32_t); | ||||
|  | ||||
| 	private: | ||||
| 		ostream &out_; | ||||
|  | ||||
| 		/** | ||||
| 		 * The entire virtual block allocation bitmap is segmented into 64-bit | ||||
| 		 * sub-bitmaps (units). | ||||
| 		 */ | ||||
| 		uint64_t bitmap; | ||||
|  | ||||
| 		/* | ||||
| 		 * Pointer to the current sub-bitmap (unit) that has not yet been | ||||
| 		 * emitted. | ||||
| 		 */ | ||||
| 		uint64_t cur; | ||||
|  | ||||
| 		/** | ||||
| 		 * Unit (sub-bitmap) size. Must be a power of 2. | ||||
| 		 */ | ||||
| 		static const size_t unit = sizeof bitmap * CHAR_BIT; | ||||
|  | ||||
| 		void emit_bmp(bool omit_if_zero = false); | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #endif /* _TMAKATOS_EMITTER_H_ */ | ||||
| @@ -21,7 +21,8 @@ persistent_data::get_nr_blocks(string const &path, sector_t block_size) | ||||
|  | ||||
| 	int r = ::stat(path.c_str(), &info); | ||||
| 	if (r) | ||||
| 		throw runtime_error("Couldn't stat dev path"); | ||||
| 		throw runtime_error("Couldn't stat dev path " + path + ": " + | ||||
| 			strerror(errno)); | ||||
|  | ||||
| 	if (S_ISREG(info.st_mode) && info.st_size) | ||||
| 		nr_blocks = div_up<block_address>(info.st_size, block_size); | ||||
|   | ||||
							
								
								
									
										22
									
								
								thin-provisioning/static_library_emitter.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								thin-provisioning/static_library_emitter.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #include "thin-provisioning/shared_library_emitter.h" | ||||
| #include <stdexcept> | ||||
| #include "contrib/tmakatos_emitter.h" | ||||
|  | ||||
| using namespace std; | ||||
| using namespace thin_provisioning; | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
|  | ||||
| emitter::ptr | ||||
| thin_provisioning::create_custom_emitter(string const &shared_lib, ostream &out) | ||||
| { | ||||
| 	if (shared_lib != "tmakatos_emitter.so") | ||||
| 		throw runtime_error(shared_lib + ": no such emitter"); | ||||
|  | ||||
| 	cout << "XXX creating tmakatos_emitter" << endl; | ||||
| 	cout << flush; | ||||
|  | ||||
| 	return emitter::ptr(new tmakatos_emitter::binary_emitter(out)); | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------- | ||||
		Reference in New Issue
	
	Block a user