示例#1
0
ReadableStore* ReadableStore::openStore(PathRef segDir, fstring fname) {
	size_t sufpos = fname.size();
	while (sufpos > 0 && fname[sufpos-1] != '.') --sufpos;
	auto suffix = fname.substr(sufpos);
	size_t idx = s_storeFactory.find_i(suffix);
	if (idx < s_storeFactory.end_i()) {
		const auto& factory = s_storeFactory.val(idx);
		ReadableStore* store = factory();
		assert(NULL != store);
		if (NULL == store) {
			THROW_STD(runtime_error, "store factory should not return NULL store");
		}
		auto fpath = segDir / fname.str();
		store->load(fpath);
		return store;
	}
	else {
		THROW_STD(invalid_argument
			, "store type '%.*s' of '%s' is not registered"
			, suffix.ilen(), suffix.data()
			, (segDir / fname.str()).string().c_str()
			);
		return NULL; // avoid compiler warning
	}
}
TERARK_DLL_EXPORT
void truncate_file(const char* fpath, unsigned long long size) {
#ifdef _MSC_VER
	Auto_close_fd fd(::_open(fpath, O_CREAT|O_BINARY|O_RDWR, 0644));
#else
	Auto_close_fd fd(::open(fpath, O_CREAT|O_RDWR, 0644));
#endif
	if (fd < 0) {
		THROW_STD(logic_error
			, "FATAL: ::open(%s, O_CREAT|O_BINARY|O_RDWR) = %s"
			, fpath, strerror(errno));
	}
#ifdef _MSC_VER
	int err = ::_chsize_s(fd, size);
	if (err) {
		THROW_STD(logic_error, "FATAL: ::_chsize_s(%s, %lld) = %s"
			, fpath, size, strerror(errno));
	}
#else
	int err = ::ftruncate(fd, size);
	if (err) {
		THROW_STD(logic_error, "FATAL: ::truncate(%s, %lld) = %s"
			, fpath, size, strerror(errno));
	}
#endif
}
	bool indexInsert(size_t indexId, fstring key, llong recId) override {
		assert(started == m_status);
		assert(indexId < m_indices.size());
		WT_ITEM item;
		WT_SESSION* ses = m_session.ses;
		const Schema& schema = m_sconf.getIndexSchema(indexId);
		WT_CURSOR* cur = m_indices[indexId].insert;
		WtWritableIndex::setKeyVal(schema, cur, key, recId, &item, &m_wrtBuf);
		int err = cur->insert(cur);
		m_sizeDiff += sizeof(llong) + key.size();
		if (schema.m_isUnique) {
			if (WT_DUPLICATE_KEY == err) {
				return false;
			}
			if (err) {
				THROW_STD(invalid_argument
					, "ERROR: wiredtiger insert unique index: %s", ses->strerror(ses, err));
			}
		}
		else {
			if (WT_DUPLICATE_KEY == err) {
				assert(0); // assert in debug
				return true; // ignore in release
			}
			if (err) {
				THROW_STD(invalid_argument
					, "ERROR: wiredtiger insert multi index: %s", ses->strerror(ses, err));
			}
		}
		return true;
	}
示例#4
0
bool LineBuf::read_binary_tuple(int32_t* offsets, size_t arity, FILE* f) {
	assert(NULL != offsets);
	offsets[0] = 0;
	size_t n_read = fread(offsets+1, 1, sizeof(int32_t) * arity, f);
	if (n_read != sizeof(int32_t) * arity) {
		return false;
	}
	for (size_t i = 0; i < arity; ++i) {
		assert(offsets[i+1] >= 0);
		offsets[i+1] += offsets[i];
	}
	size_t len = offsets[arity];
	if (this->capacity < len) {
		char* q = (char*)realloc(this->p, len);
		if (NULL == q) {
			THROW_STD(invalid_argument
				, "Out of memory when reading record[size=%zd(0x%zX)]"
				, len, len
				);
		}
		this->p = q;
		this->capacity = len;
	}
	n_read = fread(this->p, 1, len, f);
	if (n_read != len) {
		THROW_STD(invalid_argument
			, "fread record data failed: request=%zd, readed=%zd\n"
			, len, n_read
			);
	}
	this->n = len;
	return true; // len can be 0
}
示例#5
0
	void StrBuilder::setEof(int end_offset) {
		assert(end_offset < 0);
		assert(NULL != memFile);
		int rv = fflush(memFile);
		if (rv != 0) {
			THROW_STD(runtime_error, "fflush on memstream");
		}
		s[n+end_offset] = '\0';
		rv = fseek(memFile, end_offset, SEEK_END);
		if (rv != 0) {
			THROW_STD(runtime_error, "fseek on memstream");
		}
		assert(NULL != s);
		assert((long)n + end_offset >= 0);
	}
示例#6
0
void MockReadonlyStore::build(const Schema& schema, SortableStrVec& data) {
	size_t fixlen = schema.getFixedRowLen();
	if (0 == fixlen) {
		if (data.str_size() >= UINT32_MAX) {
			THROW_STD(length_error,
				"keys.str_size=%lld is too large", llong(data.str_size()));
		}
		// reuse memory of keys.m_index
		auto offsets = (uint32_t*)data.m_index.data();
		size_t rows = data.m_index.size();
		for (size_t i = 0; i < rows; ++i) {
			uint32_t offset = uint32_t(data.m_index[i].offset);
			offsets[i] = offset;
		}
		offsets[rows] = data.str_size();
		BOOST_STATIC_ASSERT(sizeof(SortableStrVec::SEntry) == 4*3);
		m_rows.offsets.risk_set_data(offsets);
		m_rows.offsets.risk_set_size(rows + 1);
		m_rows.offsets.risk_set_capacity(3 * rows);
		m_rows.offsets.shrink_to_fit();
		data.m_index.risk_release_ownership();
	#if !defined(NDEBUG)
		assert(data.m_strpool.size() == m_rows.offsets.back());
		for (size_t i = 0; i < rows; ++i) {
			assert(m_rows.offsets[i] < m_rows.offsets[i+1]);
		}
	#endif
	}
	m_rows.strpool.swap((valvec<char>&)data.m_strpool);
	m_fixedLen = fixlen;
}
示例#7
0
void ZipIntKeyIndex::getValueAppend(llong id, valvec<byte>* val, DbContext*) const {
	assert(id >= 0);
	size_t idx = size_t(id);
	assert(idx < m_keys.size());
	switch (m_keyType) {
	default:
		THROW_STD(invalid_argument, "Bad m_keyType=%s", Schema::columnTypeStr(m_keyType));
	case ColumnType::Sint08: keyAppend< int8_t >(idx, val); break;
	case ColumnType::Uint08: keyAppend<uint8_t >(idx, val); break;
	case ColumnType::Sint16: keyAppend< int16_t>(idx, val); break;
	case ColumnType::Uint16: keyAppend<uint16_t>(idx, val); break;
	case ColumnType::Sint32: keyAppend< int32_t>(idx, val); break;
	case ColumnType::Uint32: keyAppend<uint32_t>(idx, val); break;
	case ColumnType::Sint64: keyAppend< int64_t>(idx, val); break;
	case ColumnType::Uint64: keyAppend<uint64_t>(idx, val); break;
	case ColumnType::VarSint: {
		byte  buf[16];
		byte* end = save_var_int64(buf, int64_t(m_minKey + m_keys.get(idx)));
		val->append(buf, end - buf);
		break; }
	case ColumnType::VarUint: {
		byte  buf[16];
		byte* end = save_var_uint64(buf, uint64_t(m_minKey + m_keys.get(idx)));
		val->append(buf, end - buf);
		break; }
	}
}
示例#8
0
	int seekLowerBound(fstring key, llong* id, valvec<byte>* retKey) override {
		assert(key.size() == sizeof(Int));
		if (key.size() != sizeof(Int)) {
			THROW_STD(invalid_argument,
				"key.size must be sizeof(Int)=%d", int(sizeof(Int)));
		}
		auto owner = static_cast<const SeqNumIndex*>(m_index.get());
		Int keyId = unaligned_load<Int>(key.udata());
		if (keyId <= owner->m_min) {
			m_curr = 0;
			return -1;
		}
		else if (keyId > owner->m_min + owner->m_cnt) {
			m_curr = owner->m_cnt;
			*id = owner->m_cnt - 1;
			Int forwardMax = owner->m_min + owner->m_cnt - 1;
			retKey->assign((const byte*)&forwardMax, sizeof(Int));
			return 1;
		}
		else {
			keyId -= owner->m_min;
			m_curr = keyId;
			*id = keyId;
			retKey->assign(key.udata(), key.size());
			return 0;
		}
	}
	explicit WtDbTransaction(WtWritableSegment* seg)
		: m_seg(seg), m_sconf(*seg->m_schema)
	{
		WT_CONNECTION* conn = seg->m_wtConn;
		int err = conn->open_session(conn, NULL, NULL, &m_session.ses);
		if (err) {
			THROW_STD(invalid_argument
				, "FATAL: wiredtiger open session(dir=%s) = %s"
				, conn->get_home(conn), wiredtiger_strerror(err)
				);
		}
		WT_SESSION* ses = m_session.ses;
		err = ses->open_cursor(ses, g_dataStoreUri, NULL, "overwrite=true", &m_store.cursor);
		if (err) {
			THROW_STD(invalid_argument
				, "ERROR: wiredtiger store open cursor: %s"
				, ses->strerror(ses, err));
		}
		m_indices.resize(seg->m_indices.size());
		for (size_t indexId = 0; indexId < m_indices.size(); ++indexId) {
			ReadableIndex* index = seg->m_indices[indexId].get();
			WtWritableIndex* wtIndex = dynamic_cast<WtWritableIndex*>(index);
			assert(NULL != wtIndex);
			const char* uri = wtIndex->getIndexUri().c_str();
			err = ses->open_cursor(ses, uri, NULL, "overwrite=false", &m_indices[indexId].insert.cursor);
			if (err) {
				THROW_STD(invalid_argument
					, "ERROR: wiredtiger open index cursor: %s"
					, ses->strerror(ses, err));
			}
			err = ses->open_cursor(ses, uri, NULL, "overwrite=true", &m_indices[indexId].overwrite.cursor);
			if (err) {
				THROW_STD(invalid_argument
					, "ERROR: wiredtiger open index cursor: %s"
					, ses->strerror(ses, err));
			}
		}
		m_sizeDiff = 0;
		m_wrtStore = dynamic_cast<WtWritableStore*>(seg->m_wrtStore.get());
		assert(nullptr != m_store);
		g_wtDbTxnLiveCnt++;
		g_wtDbTxnCreatedCnt++;
		if (getEnvBool("TerarkDB_TrackBuggyObjectLife")) {
			fprintf(stderr, "DEBUG: WtDbTransaction live count = %zd, created = %zd\n"
				, g_wtDbTxnLiveCnt.load(), g_wtDbTxnCreatedCnt.load());
		}
	}
示例#10
0
	StrBuilder::StrBuilder() {
		s = NULL;
		n = 0;
		memFile = open_memstream(&s, &n);
		if (NULL == memFile) {
			THROW_STD(runtime_error, "open_memstream");
		}
	}
示例#11
0
ReadableStore::RegisterStoreFactory::RegisterStoreFactory
(const char* fnameSuffix, const std::function<ReadableStore*()>& f)
{
	auto ib = s_storeFactory.insert_i(fnameSuffix, f);
	assert(ib.second);
	if (!ib.second)
		THROW_STD(invalid_argument, "duplicate suffix: %s", fnameSuffix);
}
示例#12
0
bool SeqNumIndex<Int>::insert(fstring key, llong id, DbContext*) {
	assert(key.size() == sizeof(Int));
	assert(id >= 0);
	if (key.size() != sizeof(Int)) {
		THROW_STD(invalid_argument,
			"key.size must be sizeof(Int)=%d", int(sizeof(Int)));
	}
	Int keyId = unaligned_load<Int>(key.udata());
	if (keyId != m_min + id) {
		THROW_STD(invalid_argument,
			"key must be consistent with id in SeqNumIndex");
	}
	if (llong(m_cnt) < id + 1) {
		m_cnt = id + 1;
	}
	return 1;
}
示例#13
0
	StrBuilder& StrBuilder::flush() {
		assert(NULL != memFile);
		int rv = fflush(memFile);
		if (rv != 0) {
			THROW_STD(runtime_error, "fflush on memstream");
		}
	//	assert(NULL != s);
		return *this;
	}
示例#14
0
	const char* StrBuilder::c_str() {
		assert(NULL != memFile);
		int rv = fflush(memFile);
		if (rv != 0) {
			THROW_STD(runtime_error, "fflush on memstream");
		}
		assert(NULL != s);
		return s;
	}
示例#15
0
	StrBuilder::operator std::string() const {
		assert(NULL != memFile);
		int rv = fflush(memFile);
		if (rv != 0) {
			THROW_STD(runtime_error, "fflush on memstream");
		}
		assert(NULL != s);
		return std::string(s, n);
	}
示例#16
0
	void StrBuilder::setEof(int end_offset, const char* endmark) {
		assert(end_offset < 0);
		assert(NULL != endmark);
		assert(NULL != memFile);
		int rv = fseek(memFile, end_offset, SEEK_END);
		if (rv != 0) {
			THROW_STD(runtime_error, "fflush on memstream");
		}
		rv = fputs(endmark, memFile);
		if (EOF == rv) {
			THROW_STD(runtime_error, "fputs(endmark, memFile)");
		}
		rv = fflush(memFile);
		if (rv != 0) {
			THROW_STD(runtime_error, "fflush on memstream");
		}
		assert(NULL != s);
		assert((long)n + end_offset >= 0);
	}
示例#17
0
bool SeqNumIndex<Int>::replace(fstring key, llong id, llong newId, DbContext*) {
	assert(key.size() == sizeof(Int));
	assert(id >= 0);
	assert(id == newId);
	if (key.size() != sizeof(Int)) {
		THROW_STD(invalid_argument,
			"key.size must be sizeof(Int)=%d", int(sizeof(Int)));
	}
	if (id != newId) {
		THROW_STD(invalid_argument,
			"replace with different id is not supported by SeqNumIndex");
	}
	Int keyId = unaligned_load<Int>(key.udata());
	if (keyId != m_min + newId) {
		THROW_STD(invalid_argument,
			"key must be consistent with id in SeqNumIndex");
	}
	return 1;
}
示例#18
0
ptrdiff_t LineBuf::getline(FILE* f) {
	assert(NULL != f);
#if defined(__USE_GNU) || defined(__CYGWIN__) || defined(__CYGWIN32__)
       	// has ::getline
	return n = ::getline(&p, &capacity, f);
#else
//	#error only _GNU_SOURCE is supported
	if (NULL == p) {
		capacity = BUFSIZ;
		p = (char*)malloc(BUFSIZ);
		if (NULL == p)
		   	THROW_STD(runtime_error, "malloc(BUFSIZ=%d) failed", BUFSIZ);
	}
	n = 0;
	p[0] = '\0';
	for (;;) {
		assert(n < capacity);
		char*  ret = ::fgets(p + n, capacity - n, f);
		size_t len = ::strlen(p + n);
		if (0 == len && (feof(f) || ferror(f)))
			return -1;
		n += len;
		if (ret) {
			if (capacity-1 == n && p[n-1] != '\n') {
				size_t newcap = capacity * 2;
				ret = (char*)realloc(p, newcap);
				if (NULL == ret)
					THROW_STD(runtime_error, "realloc(newcap=%zd)", newcap);
				p = ret;
				capacity = newcap;
			}
			else {
				return ptrdiff_t(n);
			}
		}
		else if (feof(f))
			return ptrdiff_t(n);
		else
			return -1;
	}
#endif
}
示例#19
0
	void do_rollback() override {
		resetCursors();
#if TERARK_WT_USE_TXN
		WT_SESSION* ses = m_session.ses;
		int err = ses->rollback_transaction(ses, NULL);
		if (err) {
			THROW_STD(invalid_argument
				, "ERROR: wiredtiger rollback_transaction: %s"
				, ses->strerror(ses, err));
		}
#endif
	}
示例#20
0
	StrBuilder& StrBuilder::printf(const char* format, ...) {
		assert(NULL != format);
		assert(NULL != memFile);
		va_list ap;
		va_start(ap, format);
		int rv = vfprintf(memFile, format, ap);
		va_end(ap);
		if (rv < 0) {
			THROW_STD(runtime_error, "vfprintf on memstream");
		}
		return *this;
	}
示例#21
0
void
MockReadonlyIndex::build(SortableStrVec& keys) {
	const Schema* schema = m_schema;
	const byte* base = keys.m_strpool.data();
	size_t fixlen = schema->getFixedRowLen();
	if (fixlen) {
		assert(keys.m_index.size() == 0);
		assert(keys.str_size() % fixlen == 0);
		m_ids.resize_no_init(keys.str_size() / fixlen);
		for (size_t i = 0; i < m_ids.size(); ++i) m_ids[i] = i;
		std::sort(m_ids.begin(), m_ids.end(), [=](size_t x, size_t y) {
			fstring xs(base + fixlen * x, fixlen);
			fstring ys(base + fixlen * y, fixlen);
			int r = schema->compareData(xs, ys);
			if (r) return r < 0;
			else   return x < y;
		});
	}
	else {
		if (keys.str_size() >= UINT32_MAX) {
			THROW_STD(length_error,
				"keys.str_size=%lld is too large", llong(keys.str_size()));
		}
		// reuse memory of keys.m_index
		auto offsets = (uint32_t*)keys.m_index.data();
		size_t rows = keys.m_index.size();
		m_ids.resize_no_init(rows);
		for (size_t i = 0; i < rows; ++i) m_ids[i] = i;
		for (size_t i = 0; i < rows; ++i) {
			uint32_t offset = uint32_t(keys.m_index[i].offset);
			offsets[i] = offset;
		}
		offsets[rows] = keys.str_size();
		std::sort(m_ids.begin(), m_ids.end(), [=](size_t x, size_t y) {
			size_t xoff0 = offsets[x], xoff1 = offsets[x+1];
			size_t yoff0 = offsets[y], yoff1 = offsets[y+1];
			fstring xs(base + xoff0, xoff1 - xoff0);
			fstring ys(base + yoff0, yoff1 - yoff0);
			int r = schema->compareData(xs, ys);
			if (r) return r < 0;
			else   return x < y;
		});
		BOOST_STATIC_ASSERT(sizeof(SortableStrVec::SEntry) == 4*3);
		m_keys.offsets.risk_set_data(offsets);
		m_keys.offsets.risk_set_size(rows + 1);
		m_keys.offsets.risk_set_capacity(3 * rows);
		m_keys.offsets.shrink_to_fit();
		keys.m_index.risk_release_ownership();
	}
	m_keys.strpool.swap((valvec<char>&)keys.m_strpool);
	m_fixedLen = fixlen;
}
示例#22
0
	bool seekExact(llong id, valvec<byte>* val) override {
		auto store = static_cast<WrStore*>(m_store.get());
		SpinRwLock lock(store->m_rwMutex, false);
		if (id < 0 || id >= llong(store->m_rows.size())) {
			THROW_STD(out_of_range, "Invalid id = %lld, rows = %zd"
				, id, store->m_rows.size());
		}
		if (!store->m_rows[id].empty()) {
			*val = store->m_rows[id];
			m_id = id;
			return true;
		}
		return false;
	}
示例#23
0
llong ZipIntKeyIndex::dataInflateSize() const {
	switch (m_keyType) {
	default:
		THROW_STD(invalid_argument,
			"Bad m_keyType=%s", Schema::columnTypeStr(m_keyType));
	case ColumnType::Sint08:
	case ColumnType::Uint08: return 1 * m_keys.size();
	case ColumnType::Sint16: 
	case ColumnType::Uint16: return 2 * m_keys.size();
	case ColumnType::Sint32:
	case ColumnType::Uint32: return 4 * m_keys.size();
	case ColumnType::Sint64:
	case ColumnType::Uint64: return 8 * m_keys.size();
	}
}
示例#24
0
// static
void SchemaRecordCoder::parseToFields(const BSONObj& obj, FieldsMap* fields) {
	fields->erase_all();
//	std::string fieldnames;
	BSONForEach(elem, obj) {
	//	const char* fieldname = elem.fieldName(); // gcc-4.9.3 produce error code
		fstring fieldname = elem.fieldName(); // gcc is ok
		auto ib = fields->insert_i(fieldname);
	//	LOG(1)	<< "insert('" << fieldname.c_str() << "', len=" << fieldname.size() << ")=" << ib.first;
	//	LOG(1)	<< "find_i('" << fieldname.c_str() << "', len=" << fieldname.size() << ")=" << fields->find_i(fieldname);
		if (!ib.second) {
			THROW_STD(invalid_argument,
					"bad bson: duplicate fieldname: %s", fieldname.c_str());
		}
		invariant(fields->elem_at(ib.first).size() == fieldname.size());
//		fieldnames += fieldname.c_str();
//		fieldnames.push_back(',');
	}
示例#25
0
	void do_startTransaction() override {
#if TERARK_WT_USE_TXN
		WT_SESSION* ses = m_session.ses;
		const char* txnConfig = getenv("TerarkDB_WiredtigerTransactionConfig");
		if (NULL == txnConfig) {
		// wiredtiger 2.8.0 is not binary compatible with 2.7.0
			txnConfig = "isolation=read-committed,sync=false";
		}
	//	fprintf(stderr, "INFO: %s: txnConfig=%s\n", BOOST_CURRENT_FUNCTION, txnConfig);
		int err = ses->begin_transaction(ses, txnConfig);
		if (err) {
			THROW_STD(invalid_argument
				, "ERROR: wiredtiger begin_transaction: %s"
				, ses->strerror(ses, err));
		}
#endif
		m_sizeDiff = 0;
	}
示例#26
0
std::pair<size_t, bool>
ZipIntKeyIndex::searchLowerBound(fstring key) const {
	switch (m_keyType) {
	default:
		THROW_STD(invalid_argument, "Bad m_keyType=%s", Schema::columnTypeStr(m_keyType));
	case ColumnType::Sint08 : return IntVecLowerBound< int8_t >(key); break;
	case ColumnType::Uint08 : return IntVecLowerBound<uint8_t >(key); break;
	case ColumnType::Sint16 : return IntVecLowerBound< int16_t>(key); break;
	case ColumnType::Uint16 : return IntVecLowerBound<uint16_t>(key); break;
	case ColumnType::Sint32 : return IntVecLowerBound< int32_t>(key); break;
	case ColumnType::Uint32 : return IntVecLowerBound<uint32_t>(key); break;
	case ColumnType::Sint64 : return IntVecLowerBound< int64_t>(key); break;
	case ColumnType::Uint64 : return IntVecLowerBound<uint64_t>(key); break;
	case ColumnType::VarSint: return IntVecLowerBound< int64_t>(key); break;
	case ColumnType::VarUint: return IntVecLowerBound<uint64_t>(key); break;
	}
	abort();
	return {};
}
示例#27
0
	void indexSearch(size_t indexId, fstring key, valvec<llong>* recIdvec) override {
		assert(started == m_status);
		assert(indexId < m_indices.size());
		WT_ITEM item;
		WT_SESSION* ses = m_session.ses;
		const Schema& schema = m_sconf.getIndexSchema(indexId);
		WT_CURSOR* cur = m_indices[indexId].insert;
		WtWritableIndex::setKeyVal(schema, cur, key, 0, &item, &m_wrtBuf);
		recIdvec->erase_all();
		if (schema.m_isUnique) {
			int err = cur->search(cur);
			BOOST_SCOPE_EXIT(cur) { cur->reset(cur); } BOOST_SCOPE_EXIT_END;
			if (WT_NOTFOUND == err) {
				return;
			}
			if (err) {
				THROW_STD(invalid_argument
					, "ERROR: wiredtiger search: %s", ses->strerror(ses, err));
			}
			llong recId = 0;
			cur->get_value(cur, &recId);
			recIdvec->push_back(recId);
		}
示例#28
0
//! delete all object in list, and clear self
void AccessByNameID<void*>::destroy()
{
	std::vector<uintptr_t> used_id;
	m_byid.get_used_id(&used_id);
	std::vector<uintptr_t> bynamep(m_byname->size());
	NameMapForAccessByNameID::iterator iter = m_byname->begin();
	for (uintptr_t i = 0; iter != m_byname->end(); ++iter)
		bynamep[i++] = (uintptr_t)iter->second;
	for (uintptr_t i = 0; i != used_id.size(); ++i)
		used_id[i] = m_byid.get_val(used_id[i]);
	std::sort(used_id.begin(), used_id.end());
	std::sort(bynamep.begin(), bynamep.end());
	uintptr_t n = std::set_union(used_id.begin(), used_id.end(),
		bynamep.begin(), bynamep.end(), used_id.begin()) - used_id.begin();
	assert(used_id.size() == n);
	if (used_id.size() != n) {
		THROW_STD(runtime_error,
			"(used_id.size=%zd) != (n=%zd)", used_id.size(), n);
	}
	for (uintptr_t i = 0; i != n; ++i)
		on_destroy((void*)used_id[i]);
	m_byid.clear();
	m_byname->clear();
}
示例#29
0
void EmptyIndexStore::getValueAppend(llong id, valvec<byte>* val, DbContext*) const {
	THROW_STD(invalid_argument, "Invalid method call");
}
示例#30
0
文件: mmap.cpp 项目: rockeet/nark-db
void*
mmap_load(const char* fname, size_t* fsize, bool writable, bool populate) {
#ifdef _MSC_VER
	LARGE_INTEGER lsize;
	HANDLE hFile = CreateFileA(fname
		, GENERIC_READ |(writable ? GENERIC_WRITE : 0)
		, FILE_SHARE_DELETE | FILE_SHARE_READ | (writable ? FILE_SHARE_WRITE : 0)
		, NULL // lpSecurityAttributes
		, writable ? OPEN_ALWAYS : OPEN_EXISTING
		, FILE_ATTRIBUTE_NORMAL
		, NULL // hTemplateFile 
		);
	if (INVALID_HANDLE_VALUE == hFile) {
		DWORD err = GetLastError();
		THROW_STD(logic_error, "CreateFile(fname=%s).Err=%d(%X)"
			, fname, err, err);
	}
	if (writable) {
	//	bool isNewFile = GetLastError() != ERROR_ALREADY_EXISTS;
		bool isNewFile = GetLastError() == 0;
		if (isNewFile) {
			SetFilePointer(hFile, 8*1024, NULL, SEEK_SET);
			SetEndOfFile(hFile);
			SetFilePointer(hFile, 0, NULL, SEEK_SET);
		}
	}
	if (!GetFileSizeEx(hFile, &lsize)) {
		DWORD err = GetLastError();
		CloseHandle(hFile);
		THROW_STD(logic_error, "GetFileSizeEx(fname=%s).Err=%d(%X)"
			, fname, err, err);
	}
	if (lsize.QuadPart > size_t(-1)) {
		CloseHandle(hFile);
		THROW_STD(logic_error, "fname=%s fsize=%I64u(%I64X) too large"
			, fname, lsize.QuadPart, lsize.QuadPart);
	}
	*fsize = size_t(lsize.QuadPart);
	DWORD flProtect = writable ? PAGE_READWRITE : PAGE_READONLY;
	HANDLE hMmap = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL);
	if (NULL == hMmap) {
		DWORD err = GetLastError();
		CloseHandle(hFile);
		THROW_STD(runtime_error, "CreateFileMapping(fname=%s).Err=%d(0x%X)"
			, fname, err, err);
	}
	DWORD desiredAccess = (writable ? FILE_MAP_WRITE : 0) | FILE_MAP_READ;
	void* base = MapViewOfFile(hMmap, desiredAccess, 0, 0, 0);
	if (NULL == base) {
		DWORD err = GetLastError();
		::CloseHandle(hMmap);
		::CloseHandle(hFile);
		THROW_STD(runtime_error, "MapViewOfFile(fname=%s).Err=%d(0x%X)"
			, fname, err, err);
	}
	if (populate) {
		WIN32_MEMORY_RANGE_ENTRY vm;
		vm.VirtualAddress = base;
		vm.NumberOfBytes  = *fsize;
		PrefetchVirtualMemory(GetCurrentProcess(), 1, &vm, 0);
	}
	::CloseHandle(hMmap); // close before UnmapViewOfFile is OK
	::CloseHandle(hFile);
#else
	int openFlags = writable ? O_RDWR : O_RDONLY;
	int fd = ::open(fname, openFlags);
	if (fd < 0) {
		int err = errno;
		THROW_STD(logic_error, "open(fname=%s, %s) = %d(%X): %s"
			, fname, writable ? "O_RDWR" : "O_RDONLY"
			, err, err, strerror(err));
	}
	struct stat st;
	if (::fstat(fd, &st) < 0) {
		THROW_STD(logic_error, "stat(fname=%s) = %s", fname, strerror(errno));
	}
	*fsize = st.st_size;
	int flProtect = (writable ? PROT_WRITE : 0) | PROT_READ;
	int flags = MAP_SHARED | (populate ? MAP_POPULATE : 0);
	void* base = ::mmap(NULL, st.st_size, flProtect, flags, fd, 0);
	if (MAP_FAILED == base) {
		::close(fd);
		THROW_STD(logic_error, "mmap(fname=%s, %s SHARED, size=%lld) = %s"
			, fname, writable ? "READWRITE" : "READ"
			, (long long)st.st_size, strerror(errno));
	}
	::close(fd);
#endif
	return base;
}