Ceph入门到精通-ceph对于长文件名如何处理
RADOS object with short name
上一篇博文,我们将介绍了对象相关的数据结构ghobject_t,以及对象在底层文件系统存储的文件名,以及如何从文件名对应到 ghobject_t对象。
映射关系如下图所示:
这里面有一个漏洞,即object name的长度,如果object name长度太长,超过了本地文件系统所能支持的最长长度怎么办?
cephfs
对于cephfs而言,对象的名字是这样的:
root@185node:/var/share/ezfs/shareroot/bean_nas# dd if=/dev/zero of=bean bs=1M count=8
8+0 records in
8+0 records out
8388608 bytes (8.4 MB) copied, 0.00768172 s, 1.1 GB/s
root@185node:/var/share/ezfs/shareroot/bean_nas# cephfs bean map
WARNING: This tool is deprecated. Use the layout.* xattrs to query and modify layouts.FILE OFFSET OBJECT OFFSET LENGTH OSD0 10000000022.00000000 0 4194304 04194304 10000000022.00000001 0 4194304 1
对于cephfs中某个文件的对象是有两个部分组成的:inode 和 文件内object index, 10000000022是文件的inode,而小数点后的数字,表明的对象是文件中的第几个对象。
root@185node:/var/share/ezfs/shareroot/bean_nas# ll -li
total 8192
1099511627809 drwxrwxrwx 1 root root 1 May 29 11:39 ./
1099511627776 drwxrwxrwx 1 root root 2 May 29 11:01 ../
1099511627810 -rw-r--r-- 1 root root 8388608 May 29 11:39 bean
root@185node:/var/share/ezfs/shareroot/bean_nas# printf "%x\n" 1099511627810
10000000022
root@185node:/var/share/ezfs/shareroot/bean_nas#
对于这种情况下,objectname是很规整的,长度是有限的,我们去底层查看对象在底层文件系统的文件:
注解:bean是pool的名字,下同root@185node:/var/log# ceph osd map bean 10000000022.00000001
osdmap e44 pool 'bean' (15) object '10000000022.00000001' -> pg 15.b5ce59c5 (15.1c5) -> up ([1], p1) acting ([1], p1)root@185node:/data/osd.1/current/15.1c5_head# ll
total 4240
drwxr-xr-x 2 root root 4096 May 29 11:39 ./
drwxr-xr-x 3983 root root 135168 May 29 10:18 ../
-rw-r--r-- 1 root root 4194304 May 29 11:39 10000000022.00000001__head_B5CE59C5__f
-rw-r--r-- 1 root root 0 May 29 10:18 __head_000001C5__f
不出我们预料,对象在底层文件系统的文件名一上来就是对象的名字:10000000022.00000001
RBD
rbd的情况也类似,我们不妨创建一个rbd:
root@185node:/# rbd create -p bean --image-format=2 --size 100 rbd_test
root@185node:/# rbd -p bean ls
rbd_test
root@185node:/# rbd -p bean info rbd_test
rbd image 'rbd_test':size 102400 kB in 25 objectsorder 22 (4096 kB objects)used objects: 0block_name_prefix: rbd_data.6n2q5cs0j0o53format: 2features: layering
root@185node:/#
root@185node:/# rbd -p bean map rbd_test
/dev/rbd0
注意block_name_prefix的前缀,是rbd 内对象的前缀,我们从bean 这个pool中可以找到 rbd_data.6n2q5cs0j0o53.0000000000000000 这个objcet name,总体来讲,对象名也很规整,长度有限。
我们深入到底层文件系统,找到给对象的本地文件名,也是以object name 作为文件名的起始部分:rbd\udata.6n2q5cs0j0o53.0000000000000000
root@185node:/# ceph osd map bean rbd_data.6n2q5cs0j0o53.0000000000000000
osdmap e44 pool 'bean' (15) object 'rbd_data.6n2q5cs0j0o53.0000000000000000' -> pg 15.715f761a (15.21a) -> up ([1], p1) acting ([1], p1)root@185node:/data/osd.1/current/15.21a_head# ll
total 148
drwxr-xr-x 2 root root 4096 May 29 11:57 ./
drwxr-xr-x 3983 root root 135168 May 29 10:18 ../
-rw-r--r-- 1 root root 0 May 29 10:18 __head_0000021A__f
-rw-r--r-- 1 root root 513 May 29 11:57 rbd\udata.6n2q5cs0j0o53.0000000000000000__head_715F761A__f
但是RADOS object是cephfs 和 RBD的基石,RADOS是支持比较长的object name的,如下面的commit所说,RADOS是支持长达2048字节的对象名的。
commit 7e0aca18a04a3848af77f5dd2093dc2e009386ec
Author: Sage Weil <sage@redhat.com>
Date: Wed Jul 16 14:17:27 2014 -0700osd: add config for osd_max_object_name_len = 2048 (was hard-coded at 4096)Previously we had a hard coded limit of 4096. Objects > 3k crash the OSDwhen running on ext4, although they probably work on xfs. But rgw onlygenerates objects a bit over 1024 bytes (maybe 1200 tops?), so let set amore reasonable limit here. 2048 is a nice round number and should besafe.Add a test.Fixes: #8174Signed-off-by: Sage Weil <sage@redhat.com>
但是很不幸,本地文件系统并没有这么强悍,支持的文件名长度都有限:
FS | max filename length in bytes |
---|---|
EXT4 | 255 |
XFS | 255 |
ZFS | 255 |
btrfs | 255 |
这就必然带来问题,因为文件尚且不能存放下object name,更谈不上其他hash之类的字段。Ceph是如何破解这个难题的呢?
RADOS object with long name
我们不妨通过rados 命令创建一个具有超长 object name的对象:
首先我们产生一个随机的足够长的名字:
root@185node:/# xxd -l $((2048/2)) -p /dev/urandom | tr -d '\n'
acda7ad8b034a90f9b980be5ed47e242209061c2515c2021b83f1f8c49d018d621a14043a68be64ecec025a1434f040c853b7419c0c571c6b20a5e4a25fe7bf2ff181b60508622bf89f7818add55022ba17d6c9f8bd2938d97788964d0da8405a29d5fa77b07b6e4484b5335b20c9e6eb2f89bf7e805256185b580f075008815cad96f79893599b3718d0dbc05796238c2cf22cd4ee0fadc3891951bbffb0602f3b14b3af7b1efe4c96a340de12fa3ba3f4baeb166768326cfe6d79ee210228266f292bdce01eb6d5c6eb4c64ac619d1aa3853d65a614e109638bf7e04389c8b9a06b41492e65a187abc834bfd6fc4988a55c9b2ed5b91a129acf572d6661fa1cac6ce4fb181b005883b38ca600e9004244fb6ff13cde1939c54583a3dc284cd82a6f77ee171a7b7423b040fc6a65070a6ff98a8b45fd3b1de8c325e6ec00c18d077ea6442b9b134fb9d515ea51427ef8dc43bb524c0a2e6958092186e1e3ae6058b114a5d7abfd7056e55596336f9191269731b71c240e1a449b4a83094fe5d5fe2143bcb19a0f913fb4a836f317a32cf74f91b1091b1c16644b39e0ec4dbfc6ec31f9a1da6c2e6c457e976e709b68c921f630fda53185ddc5c9454a63966b5982bc0905a84f134ee7e6187b9e2cd63b4a0fb174bf626c62400517cfb6121df951b3e0e895c1c2c1bd20dc73231f91e2d692c38d2f02f91158c824104c148d08c0ac2e363d7811d964a5fa6415a477e9ac2b304b51e66c52d7ec5d3214bd5f96044a0b96fe6e29a76b2e7818a41ff50db3ebc11eade7089e03237fcb913b17c5ff6de04278ffd7754c62951e493b4044ee916dce246898724a1306c6eae97a689dc9df3f69b42aae6071b00140a8a5d09e67b732c5f093eefc7ca719a7a6d3e5f53f9a36f8a4c9a9e28d19854559f911e1b42ef66ec1a5126ee2adb1d14dc10504a6c00063babea88c1c2b6e97581f771a099388a12d1050a6fe26cba538517195ed399053bd29467422064d8f6dd0661efa9e08f432c0f8ecf42bc589fa357547dc9313da0b172514d4aa102b8a6e01f0205e3c36db2102a7788924d6d314beff379c55d9dc433520355947f4da74038b4f263d74629cac1fa1248b4a89ced59a9005b667f3923b28bb80081429baf8a2748f3f84f31213b660046c22329cf1d3de4f2636be1257c0c8de15cc945f901db2243192802c92162fffef4eee3d4f5aeb9228291d6b89df6ef7c495f9041c65e386a8d77d3ba4b6bc19f0d049d07a49ca95deac3242d0ae8f643df4c65eae119f73516da42e17f8a06b9ea17e1bf248a50b57b870be2cf2269314534a17e77fc0266e05651169a0be11328371dd426d72cb51fa7e1ab5f75f55c0db9453824eeaaa1e156b5c0e0ba27e1f2f99b0733b2b6f004f8dd9f41321b6c24d36ccda327cadc85d97132878c40bb03252cb0
其次,我们通过rados 命令,创建一个该名字的object,对象的内容是“hello world”
root@185node:/# rados --pool=bean put acda7ad8b034a90f9b980be5ed47e242209061c2515c2021b83f1f8c49d018d621a14043a68be64ecec025a1434f040c853b7419c0c571c6b20a5e4a25fe7bf2ff181b60508622bf89f7818add55022ba17d6c9f8bd2938d97788964d0da8405a29d5fa77b07b6e4484b5335b20c9e6eb2f89bf7e805256185b580f075008815cad96f79893599b3718d0dbc05796238c2cf22cd4ee0fadc3891951bbffb0602f3b14b3af7b1efe4c96a340de12fa3ba3f4baeb166768326cfe6d79ee210228266f292bdce01eb6d5c6eb4c64ac619d1aa3853d65a614e109638bf7e04389c8b9a06b41492e65a187abc834bfd6fc4988a55c9b2ed5b91a129acf572d6661fa1cac6ce4fb181b005883b38ca600e9004244fb6ff13cde1939c54583a3dc284cd82a6f77ee171a7b7423b040fc6a65070a6ff98a8b45fd3b1de8c325e6ec00c18d077ea6442b9b134fb9d515ea51427ef8dc43bb524c0a2e6958092186e1e3ae6058b114a5d7abfd7056e55596336f9191269731b71c240e1a449b4a83094fe5d5fe2143bcb19a0f913fb4a836f317a32cf74f91b1091b1c16644b39e0ec4dbfc6ec31f9a1da6c2e6c457e976e709b68c921f630fda53185ddc5c9454a63966b5982bc0905a84f134ee7e6187b9e2cd63b4a0fb174bf626c62400517cfb6121df951b3e0e895c1c2c1bd20dc73231f91e2d692c38d2f02f91158c824104c148d08c0ac2e363d7811d964a5fa6415a477e9ac2b304b51e66c52d7ec5d3214bd5f96044a0b96fe6e29a76b2e7818a41ff50db3ebc11eade7089e03237fcb913b17c5ff6de04278ffd7754c62951e493b4044ee916dce246898724a1306c6eae97a689dc9df3f69b42aae6071b00140a8a5d09e67b732c5f093eefc7ca719a7a6d3e5f53f9a36f8a4c9a9e28d19854559f911e1b42ef66ec1a5126ee2adb1d14dc10504a6c00063babea88c1c2b6e97581f771a099388a12d1050a6fe26cba538517195ed399053bd29467422064d8f6dd0661efa9e08f432c0f8ecf42bc589fa357547dc9313da0b172514d4aa102b8a6e01f0205e3c36db2102a7788924d6d314beff379c55d9dc433520355947f4da74038b4f263d74629cac1fa1248b4a89ced59a9005b667f3923b28bb80081429baf8a2748f3f84f31213b660046c22329cf1d3de4f2636be1257c0c8de15cc945f901db2243192802c92162fffef4eee3d4f5aeb9228291d6b89df6ef7c495f9041c65e386a8d77d3ba4b6bc19f0d049d07a49ca95deac3242d0ae8f643df4c65eae119f73516da42e17f8a06b9ea17e1bf248a50b57b870be2cf2269314534a17e77fc0266e05651169a0be11328371dd426d72cb51fa7e1ab5f75f55c0db9453824eeaaa1e156b5c0e0ba27e1f2f99b0733b2b6f004f8dd9f41321b6c24d36ccda327cadc85d97132878c40bb03252cb0 <(echo "hello,world")
通过ceph osd map 命令,找到该对象的所在的OSD :
-> pg 15.5939415b (15.15b) -> up ([0], p0) acting ([0], p0)
我们去本地文件系统去寻找该对象对应的文件:
root@185node:/data/osd.0/current/15.15b_head# ll
total 152
drwxr-xr-x 2 root root 4096 May 29 10:38 ./
drwxr-xr-x 3961 root root 135168 May 29 10:18 ../
-rw-r--r-- 1 root root 12 May 29 10:38 acda7ad8b034a90f9b980be5ed47e242209061c2515c2021b83f1f8c49d018d621a14043a68be64ecec025a1434f040c853b7419c0c571c6b20a5e4a25fe7bf2ff181b60508622bf89f7818add55022ba17d6c9f8bd2938d97788964d0da8405a29d5fa77b07b6e4484b5335b20c9e6eb2f_8293d87c929eba91a280_0_long
-rw-r--r-- 1 root root 0 May 29 10:18 __head_0000015B__f
很明显,本地文件系统是不可能存放下长度达1K这么长的名字的,那ceph是怎么做的呢?对于长的object name,ceph是如何处理的呢?
从存储在本地文件系统的名字来看,文件名分成4个部分
- object name prefix ,长度为FILENAME_PREFIX_LEN
- object name 的 SHA-1 hash,注意是完整object name的SHA-1 hash
- candidate index , 调用lfn_get_name函数时传递的参数值
- FILENAME_COOKIE 静态字符串,就是‘long’ 这个字符串。
这四个部分通过下划线_分隔开。
这部分逻辑时在build_filename函数实现的:
void LFNIndex::build_filename(const char *old_filename, int i, char *filename, int len)
{char hash[FILENAME_HASH_LEN + 1];assert(len >= FILENAME_SHORT_LEN + 4);strncpy(filename, old_filename, FILENAME_PREFIX_LEN);filename[FILENAME_PREFIX_LEN] = '\0';if ((int)strlen(filename) < FILENAME_PREFIX_LEN)return;if (old_filename[FILENAME_PREFIX_LEN] == '\0')return;hash_filename(old_filename, hash, sizeof(hash));int ofs = FILENAME_PREFIX_LEN;while (1) {int suffix_len = sprintf(filename + ofs, "_%s_%d_%s", hash, i, FILENAME_COOKIE.c_str());if (ofs + suffix_len <= FILENAME_SHORT_LEN || !ofs)break;ofs--;}
}
这部分逻辑比较简单,如果old_filename 即原始的object name长度有限,比FILENAME_PREFIX_LEN 要短的话,那就说明时短的对象名,什么处理也不用做,直接将名字赋值给filename 即可。 但是如果old_filename 很长,就要计算名字的hash,组成长的文件名,即上面提到的4段式。
#define CEPH_CRYPTO_SHA1_DIGESTSIZE 20class LFNIndex : public CollectionIndex {/// Hash digest output size.static const int FILENAME_LFN_DIGEST_SIZE = CEPH_CRYPTO_SHA1_DIGESTSIZE;/// Length of filename hash.static const int FILENAME_HASH_LEN = FILENAME_LFN_DIGEST_SIZE;/// Max filename size.static const int FILENAME_MAX_LEN = 4096;/// Length of hashed filename.static const int FILENAME_SHORT_LEN = 255;/// Length of hashed filename prefix.static const int FILENAME_PREFIX_LEN;/// Length of hashed filename cookie.static const int FILENAME_EXTRA = 4;/// Lfn cookie value.static const string FILENAME_COOKIE;/// Name of LFN attribute for storing full name.static const string LFN_ATTR;/// Prefix for subdir index attributes.static const string PHASH_ATTR_PREFIX;/// Prefix for index subdirectories.static const string SUBDIR_PREFIX;
const int LFNIndex::FILENAME_PREFIX_LEN = FILENAME_SHORT_LEN - FILENAME_HASH_LEN -FILENAME_COOKIE.size() -FILENAME_EXTRA;const string LFNIndex::FILENAME_COOKIE = "long";
有时候需要根据ghoject_t 来生成段的短的文件名:
string LFNIndex::lfn_get_short_name(const ghobject_t &oid, int i)
{string long_name = lfn_generate_object_name(oid);assert(lfn_must_hash(long_name));char buf[FILENAME_SHORT_LEN + 4];build_filename(long_name.c_str(), i, buf, sizeof(buf));return string(buf);
}
因为短的文件名是长的object name的摘要,必然会有数据的损失,因此,需要判断短的文件名和长的文件名是否匹配:
bool LFNIndex::short_name_matches(const char *short_name, const char *cand_long_name)
{const char *end = short_name;while (*end) ++end;const char *suffix = end;if (suffix > short_name) --suffix; // last charwhile (suffix > short_name && *suffix != '_') --suffix; // back to first _if (suffix > short_name) --suffix; // one behind thatwhile (suffix > short_name && *suffix != '_') --suffix; // back to second _int index = -1;char buf[FILENAME_SHORT_LEN + 4];assert((end - suffix) < (int)sizeof(buf));int r = sscanf(suffix, "_%d_%s", &index, buf);if (r < 2)return false;if (strcmp(buf, FILENAME_COOKIE.c_str()) != 0)return false;build_filename(cand_long_name, index, buf, sizeof(buf));return strcmp(short_name, buf) == 0;
}
注意,刚才我提到了,SHA1本质是摘要,如果文件名从2K截断成200+字节,纵然提供了SHA1摘要,也是有数据损失的,如何根据磁盘上的文件重新获取object的所有信息呢。靠文件名肯定是不行了,有数据丢失,而且不可逆,恢复不回来object的所有信息。
ceph采用的xattr。这几天一直想先写ceph的chain_xattr, 但总觉的简单,而且机缘不到。我们先讲述原理,至于xattr,并不复杂。
root@185node:/data/osd.0/current/15.15b_head# getfattr -d acda7ad8b034a90f9b980be5ed47e242209061c2515c2021b83f1f8c49d018d621a14043a68be64ecec025a1434f040c853b7419c0c571c6b20a5e4a25fe7bf2ff181b60508622bf89f7818add55022ba17d6c9f8bd2938d97788964d0da8405a29d5fa77b07b6e4484b5335b20c9e6eb2f_8293d87c929eba91a280_0_long
# file: acda7ad8b034a90f9b980be5ed47e242209061c2515c2021b83f1f8c49d018d621a14043a68be64ecec025a1434f040c853b7419c0c571c6b20a5e4a25fe7bf2ff181b60508622bf89f7818add55022ba17d6c9f8bd2938d97788964d0da8405a29d5fa77b07b6e4484b5335b20c9e6eb2f_8293d87c929eba91a280_0_long
user.ceph.snapset=0sAgIZAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA==
user.cephos.lfn3="acda7ad8b034a90f9b980be5ed47e242209061c2515c2021b83f1f8c49d018d621a14043a68be64ecec025a1434f040c853b7419c0c571c6b20a5e4a25fe7bf2ff181b60508622bf89f7818add55022ba17d6c9f8bd2938d97788964d0da8405a29d5fa77b07b6e4484b5335b20c9e6eb2f89bf7e805256185b580f075008815cad96f79893599b3718d0dbc05796238c2cf22cd4ee0fadc3891951bbffb0602f3b14b3af7b1efe4c96a340de12fa3ba3f4baeb166768326cfe6d79ee210228266f292bdce01eb6d5c6eb4c64ac619d1aa3853d65a614e109638bf7e04389c8b9a06b41492e65a187abc834bfd6fc4988a55c9b2ed5b91a129acf572d6661fa1cac6ce4fb181b005883b38ca600e9004244fb6ff13cde1939c54583a3dc284cd82a6f77ee171a7b7423b040fc6a65070a6ff98a8b45fd3b1de8c325e6ec00c18d077ea6442b9b134fb9d515ea51427ef8dc43bb524c0a2e6958092186e1e3ae6058b114a5d7abfd7056e55596336f9191269731b71c240e1a449b4a83094fe5d5fe2143bcb19a0f913fb4a836f317a32cf74f91b1091b1c16644b39e0ec4dbfc6ec31f9a1da6c2e6c457e976e709b68c921f630fda53185ddc5c9454a63966b5982bc0905a84f134ee7e6187b9e2cd63b4a0fb174bf626c62400517cfb6121df951b3e0e895c1c2c1bd20dc73231f91e2d692c38d2f02f91158c824104c148d08c0ac2e363d7811d964a5fa6415a477e9ac2b304b51e66c52d7ec5d3214bd5f96044a0b96fe6e29a76b2e7818a41ff50db3ebc11eade7089e03237fcb913b17c5ff6de04278ffd7754c62951e493b4044ee916dce246898724a1306c6eae97a689dc9df3f69b42aae6071b00140a8a5d09e67b732c5f093eefc7ca719a7a6d3e5f53f9a36f8a4c9a9e28d19854559f911e1b42ef66ec1a5126ee2adb1d14dc10504a6c00063babea88c1c2b6e97581f771a099388a12d1050a6fe26cba538517195ed399053bd29467422064d8f6dd0661efa9e08f432c0f8ecf42bc589fa357547dc9313da0b172514d4aa102b8a6e01f0205e3c36db2102a7788924d6d314beff379c55d9dc433520355947f4da74038b4f263d74629cac1fa1248b4a89ced59a9005b667f3923b28bb80081429baf8a2748f3f84f31213b660046c22329cf1d3de4f2636be1257c0c8de15cc945f901db2243192802c92162fffef4eee3d4f5aeb9228291d6b89df6ef7c495f9041c65e386a8d77d3ba4b6bc19f0d049d07a49ca95deac3242d0ae8f643df4c65eae119f73516da42e17f8a06b9ea17e1bf248a50b57b870be2cf2269314534a17e77fc0266e05651169a0be11328371dd426d72cb51fa7e1ab5f75f55c0db9453824eeaaa1e156b5c0e0ba27e1f2f99b0733b2b6f004f8dd9f41321b6c24d36ccda327cadc85d97132878c40bb03252cb0"
user.cephos.lfn3@1="__head_5939415B__f"
user.cephos.spill_out=0sMQA=root@185node:/data/osd.0/current/15.15b_head#
注意该短文件名对应的文件有扩展属性信息:
- user.cephos.lfn3
- user.cephos.lfn3@1
ceph将object 所有需要的信息都存放在 user.cephos.lfn$INDEX_VERSION 这个扩展属性里面。 但是为什么冒出来个user.cephos.lfn3@1, 这就是chain_xattr的含义了。2个Linux 扩展属性信息存放的是一笔扩展属性,仅仅是因为EXT4这个本地文件系统扩展属性中value能存放的数据非常有限 2K,没有办法将value存放在单个key对应的 扩展属性里面,所以使用多个key来描述一个属性。这就是chain_xattr中chain的含义。
即如果你希望存放一个key value到Linux文件系统的某个文件的扩展属性中,受限于扩展属性能容纳的value长度有限,你不得不这么存放:
key key@1 key@2 key@3
OK,都讲完了,还是有一些代码需要梳理,先到此处吧。我也累了。
相关文章:
Ceph入门到精通-ceph对于长文件名如何处理
RADOS object with short name 上一篇博文,我们将介绍了对象相关的数据结构ghobject_t,以及对象在底层文件系统存储的文件名,以及如何从文件名对应到 ghobject_t对象。 映射关系如下图所示: 这里面有一个漏洞,即obje…...
vue+element-ui 项目实战示例详解【目录】
vue 和 element是两个流行的前端即时,通常用于管理后台,PC等页面 能够快速构建美观的界面 1. vue2 介绍 Vue.js是一个流行的JavaScript框架,用于构建用户界面。它的版本分为Vue 2和Vue 3,而Element是一个基于Vue.js 2的UI组件库。…...
性能测试-性能调优主要方向和原则(15)
性能调优主要方向明确性能瓶颈之后,就需要进行性能调优了,调优主要从图所示的多个方向入手。能优化手段并不一定是独立应用的,在一次优化过程中很可能应用了多种优化技巧。 硬件层面优化 硬件层面优化更偏向于监控,当定位到硬件资源成为瓶颈后,更多是采用扩容等手段来解决…...
关于taos数据库使用过程中突发“unable to establish connection”问题解决
项目使用的版本信息 1.taos的版本信息 3.0.4.1 2.jdbc的版本 3.2.1 3.druid连接池版本 1.2.11问题描述 Java应用服务连接,突然大量抛出如下的异常信息导致应用宕机: sql: select server_status(), desc: unable to establish connection和集团DBA沟通…...
【Qt】Qt中将字符串转换为数字类型的函数总结以及用法示例
在Qt中,可以使用以下函数将字符串转换为数字类型: toInt():将字符串转换为int类型。toDouble():将字符串转换为double类型。toFloat():将字符串转换为float类型。toLongLong():将字符串转换为long long类型…...
效率工具3-计算机网络工具
查看各个状态的tcp连接情况 netstat -n | awk ‘/^tcp/ {S[$NF]} END {for(a in S) print a, S[a]}’ /^tcp/ 正则表达式匹配 netstat 命令输出的匹配部分,即以 "TCP" 开始的行{S[$NF]} 对于符合条件的每一行,awk 命令将使用数组 S 来计算每…...
2万多条汉字笔画笔顺查询ACCESS\EXCEL数据库
发现很多新华字典类的数据都没有笔顺的相关数据,因此就找了一下笔顺查询相关,发现有两个模式,一种是每个字每个笔画都有一张图片(很庞大的图片数据量);一种是笔画图片文件显示型,比如今天采集的…...
我的一周年创作纪念日,感谢有你们
机缘 还记得 2022 年 09 月 19 日吗? 我撰写了第 1 篇技术博客:《纯CSS实现Material文本框(PC和移动端都可以使用)》;从此就开始了我在CSDN记录日常工作中开发和学习的第一步。在后续又参加了新星计划,取得…...
【音视频】ffplay源码解析-PacketQueue队列
包队列架构位置 对应结构体源码 MyAVPacketList typedef struct MyAVPacketList {AVPacket pkt; //解封装后的数据struct MyAVPacketList *next; //下一个节点int serial; //播放序列 } MyAVPacketList;PacketQueue typedef struct PacketQueue {MyAVPacketList …...
C++ 霍夫变换圆形检测
霍夫变换圆形检测 一、检测原理二、实现步骤三、算法实现一、检测原理 HoughCircles 参数说明: HoughCircles( InputArray image, // 输入图像 ,必须是 8 位的单通道灰度图像 OutputArray circles, // 输出结果,发现的圆信息 Int method, // 方法 - HOUGH…...
南阳师范学院图书馆藏《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著——2023学生开学季辉少许
南阳师范学院图书馆藏《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著——2023学生开学季辉少许...
如何将你在树莓派上部署的 IoT 物联网 MQTT 服务发布到公网?
上一章,你成功的在树莓派搭建了 EMQX 开源社区版,用来提供 MQTT 服务,并验证了设备端接入和消息通信。但你发现只能在局域网内访问 emqx.local 服务,而 IoT 设备分布在全国各地公共网络环境,这些设备该如何接入呢&a…...
系统架构设计师(第二版)学习笔记----软件工程
【原文链接】系统架构设计师(第二版)学习笔记----软件工程 文章目录 一、软件工程1.1 软件危机的表现1.2 软件工程的内容 二、软件过程模型2.1 软件的声明周期2.2 瀑布模型2.3 瀑布模型的缺点2.4 原型模型2.5 原型模型开发阶段2.6 开发原型的途径2.7 螺旋…...
C与C++字符串分割方法示例汇总
在C语言中,没有内置的字符串分割函数。但是,你可以使用其他字符串操作函数和循环来实现字符串分割。这里是使用 strtok 函数在C中分割字符串的示例: #include <stdio.h> #include <string.h> int main() {char str[] "Hel…...
HTTP代理与VPN:网络代理技术的比较
HTTP代理和VPN是两种常见的网络代理技术,它们可以帮助用户隐藏自己的IP地址、保护网络隐私、绕过网络限制等。本文将介绍HTTP代理和VPN的定义、工作原理、优缺点以及使用场景。 一、HTTP代理 HTTP代理是一种通过代理服务器转发网络请求的技术。当用户发起网络请求时…...
免费低代码平台,助企业高效管理任务
编者按:本文主要介绍了免费的低代码平台实现了高效的任务管理系统,助力企业在任务管理方面的效率更上一层楼!这个免费的低代码平台,将提高员工的工作效率。它不仅是一个任务管理系统,更是一个能让 企业 摆脱繁琐工作&a…...
基于conda的相关命令
conda 查看python版本环境 打开Anaconda Prompt的命令输入框 查看自己的python版本 conda env list激活相应的python版本(环境) conda avtivate python_3.9 若输入以下命令可查看python版本 python -V #注意V是大写安装相应的包 pip install 包名5.查看已安装…...
【微信小程序】swiper的使用
1.swiper的基本使用 <jxz-header></jxz-header> <view class"banner"><swiperprevious-margin"30rpx"autoplayinterval"2000"indicator-dotsindicator-color"rgba(0,0,0,0.3)"indicator-active-color"#bda…...
iText实战--PDF和iText 简介
PDF可以做如下事务 iText 5步创建PDF import java.io.FileOutputStream; import com.itextpdf.text.Document; import com.itextpdf.text.Paragraph; import com.itextpdf.text.pdf.PdfWriter;public class PdfHelloWorld {/*** param args*/public static void main(String[]…...
「大数据-0.1」虚拟机VMware安装、配置、使用、创建大数据集群教程
目录 一、下载VMware Wworkstation Pro 16 二、安装VMware Wworkstation Pro 16 三、检查与设置VMware的网卡 1. 检查 2. 设置VMware网段 四、在VMware上安装Linux虚拟机 五、对安装好的虚拟机进行设置 1. 打开设置 2. 设置中文 3. 修改字体大小 4. 修改终端字体大小 5. 关闭虚…...
【HTTP】GET 和 POST 的区别
GET 和 POST 的区别 首先: GET 和 POST 没有本质区别, 具体来说, GET 的使用场景可替换为 POST,POST 使用的场景也可以替换为 GET. 语义上的区别: GET 通常用来获取数据, POST 通常用来上传数据. 现状是 GET 也经常用来上传数据, POST 也经常用来获取数据. 数据存放的位置不同…...
Unity Asset Bundle Browser 工具
Unity Asset Bundle Browser 工具 您可以在 Unity 项目中使用 Asset Bundle Browser 工具能够查看和编辑资源包的配置。 有关更多信息,请参阅 Unity Asset Bundle Browser 文档。 注意:此工具是不受支持的实用程序。查看极大的资源包可能会导致性能下…...
使用Linkerd实现流量管理:学习如何使用Linkerd的路由规则来实现流量的动态控制
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...
1462. 课程表 IV
文章目录 Tag题目来源题目解读解题思路方法一:Floyd传递闭包方法二:拓扑排序 思考写在最后 Tag 【拓扑排序】【传递闭包】【并查集】【数组】 题目来源 1462. 课程表 IV 题目解读 给你一个表示课程先决条件的数组 prerequisites,prerequis…...
QTday2
完善登录框 点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容“账号密码不匹配,是否重新登录”,给定两个按钮…...
thrift的简单使用
写在前面 本文一起看下一种由facebook出品的rpc框架thrift。 源码 。 1:开发步骤 1:编写thrift idl文件 2:根据thrift idl文件生成java模板代码 3:继承模板代码的*.Iface接口给出server的具体服务实现 4:使用模板的HelloWorldSe…...
Python实现猎人猎物优化算法(HPO)优化随机森林分类模型(RandomForestClassifier算法)项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的…...
2023年7月京东平板电脑行业品牌销售排行榜(京东销售数据分析)
鲸参谋监测的京东平台7月份平板电脑市场销售数据已出炉! 根据鲸参谋电商数据分析平台的相关数据显示,今年7月份,京东平台上平板电脑的销量为68万,同比增长超过37%;销售额为22亿,同比增长约54%。从价格上看…...
HTML显示中文空格字符,emsp;一个中文字符,ensp;半个中文字符
 一个中文字符  半个中文字符 <ul><li class"li">姓  名:<input type"text" /></li><li class"li">手 机 号:<input type"…...
Python基础指令(上)
Python基础指令上 常量和表达式变量和类型1. 什么是变量2. 变量的语法2.1 定义变量2.2 使用变量 3. 变量的类型4. 为什么要有这么多类型5. 动态类型特性 注释输入输出1. 程序与用户的交互2. 通过控制台输出3. 通过控制台输入 运算符1. 算术运算符2. 关系运算符3. 逻辑运算符4. …...
淮阳 网站建设/百度高级搜索引擎入口
SAM很好用的啊。。。 传送门 双倍经验:L-Gap Substrings 基本做法类似,这道题的差分改掉,map 改掉就好了QWQ noteskey 反正就是先差分一下,然后把首项丢掉(没有比较的对象自然就不算趋势了) 然后就是建 SAM…...
沂源放心企业网站建设方案报价/百度pc端网页版
题目在这里啊 A.最长上升子序列,范围很小所以写了简单的O(n^2)算法 #include <iostream>#define rep(i, j, k) for(int i j;i < k;i )#define rev(i, j, k) for(int i j;i > k;i --)using namespace std;typedef long long ll;int n, m, a[1111], f[1…...
三河市最新消息/seo技术交流论坛
拿到Nuvi 350的时候,我惊讶不已,有这么小巧的GPS?竟然比PDA还要小一点点。把玩了一下,喜欢的不得了。下面我就同大家一起来分享我的Nuvi 350试用手记。 很早就去浏览台湾的Garmin网站,对在台湾新上市的Nuvi 350心仪不已…...
在线python编程网页/seo咨询推广
什么是 Visual Paradigm IT项目管理框架? 框架是一组工具,可以帮助您更快,更好地完成工作。IT项目管理框架是一个概念,方法和工具的集合,帮助项目团队实现以下目标。 管理项目生命周期:从项目识别到项目启动…...
做公司做网站有用吗/培训教育
在Qt的model/view中,QStandardItem是可以设置复选效果的,在QTreeView和QTableView等中以QCheckBox的样子显示出来。 item->setCheckable(true); // 设置是否能复选(默认只有√和两种形态) item->setTristate(true); …...
哪些网站做简历合适/seo关键词排名公司
redis集群 java架构师项目实战,高并发集群分布式,大数据高可用,视频教程在redis3.0之前,出现了sentinel工具来监控各个Master的状态(可以看上一篇博客)。如果Master异常则会做主从切换。选举一个slave作为新的Master,3.0之后出现了…...