[00:00.000 --> 00:07.000] Well, with something you want to do. [00:07.000 --> 00:10.000] Okay, I think we can start. [00:10.000 --> 00:12.000] Let's see if this works. [00:12.000 --> 00:15.000] Yes. [00:15.000 --> 00:18.000] So, yeah, where am I? [00:18.000 --> 00:20.000] I am Frédéric Decaux. I'm local. [00:20.000 --> 00:21.000] I'm from Belgium. [00:21.000 --> 00:23.000] So, this is why I'm often here. [00:23.000 --> 00:27.000] You can follow me on Twitter as Lefret. [00:27.000 --> 00:30.000] So, if you have any questions, just ask me. [00:30.000 --> 00:33.000] I'm quite old using MySQL. [00:33.000 --> 00:35.000] I started with MySQL 3.20. [00:35.000 --> 00:38.000] I was thinking it was 3.23, but it was 3.20. [00:38.000 --> 00:42.000] I found the CD at home. [00:42.000 --> 00:44.000] Yes, a CD for people who don't know what it is. [00:44.000 --> 00:48.000] Before there was a program in it, and before that was Floppy. [00:48.000 --> 00:49.000] I also knew the Floppy. [00:49.000 --> 00:52.000] So, as I said, I live in Belgium, and I have a blog [00:52.000 --> 00:56.000] where you can find a lot of information mostly related to MySQL. [00:56.000 --> 01:01.000] So, today I'm going to talk about the component infrastructure. [01:01.000 --> 01:02.000] I'm very sorry. [01:02.000 --> 01:05.000] Usually we are in a very dark room where... [01:05.000 --> 01:08.000] and I changed my slide to be dark slides, [01:08.000 --> 01:12.000] but to make it to see them very well, but it seems not okay. [01:12.000 --> 01:19.000] So, we will see that if you want to modify MySQL, [01:19.000 --> 01:24.000] you have different ways, creating a storage engine. [01:24.000 --> 01:26.000] That's one way to modify MySQL. [01:26.000 --> 01:31.000] I want to have my own storage engine to store the data like I want. [01:31.000 --> 01:33.000] I want to create a plugin. [01:33.000 --> 01:37.000] Next session is about that, right? [01:37.000 --> 01:42.000] Vinicius, and or by creating a component. [01:42.000 --> 01:47.000] We at MySQL, we encourage you to use this component infrastructure [01:47.000 --> 01:53.000] if you want to extend MySQL over the plugin, for example. [01:53.000 --> 01:57.000] It's very, very not easy to read for you, sorry. [01:57.000 --> 02:01.000] So, what is this MySQL component infrastructure? [02:01.000 --> 02:05.000] So, it's a modular design for the MySQL server [02:05.000 --> 02:09.000] that will allow the developers to extend the server, [02:09.000 --> 02:12.000] like I said earlier, right, in a different way, [02:12.000 --> 02:16.000] and such adding support for new functions, [02:16.000 --> 02:20.000] new performance schema table, new status variable, [02:20.000 --> 02:24.000] new system variable, all that kind of stuff [02:24.000 --> 02:26.000] that you want to extend to MySQL, [02:26.000 --> 02:30.000] you will be able to use the component infrastructure to do that. [02:30.000 --> 02:32.000] And so, what does it mean? [02:32.000 --> 02:35.000] It means that the server will provide you services [02:35.000 --> 02:39.000] that you can use to extend MySQL. [02:39.000 --> 02:44.000] And there is, you don't see it very well here, [02:44.000 --> 02:48.000] but there is a component service inventory page. [02:48.000 --> 02:50.000] The URL is here. [02:50.000 --> 02:52.000] Yes, you will have the slide online, [02:52.000 --> 02:57.000] so you can read them and copy the URL. [02:57.000 --> 03:01.000] And something very nice is that this component infrastructure [03:01.000 --> 03:05.000] is, or you say that, enhancing all the time. [03:05.000 --> 03:08.000] So, for example, in MySQL 8028, [03:08.000 --> 03:13.000] we had 137 services defined that you could use, [03:13.000 --> 03:17.000] and in 8032, it's already 162 services. [03:17.000 --> 03:21.000] So, if there is something you would like to do [03:21.000 --> 03:23.000] and you don't know how to do it, [03:23.000 --> 03:25.000] it's something you can ask us. [03:25.000 --> 03:28.000] I don't say it's guaranteed that you will have it in the next version, [03:28.000 --> 03:30.000] but it's something we are doing. [03:30.000 --> 03:32.000] We try to improve. [03:32.000 --> 03:34.000] And internally, it's the same. [03:34.000 --> 03:37.000] So, when one of the teams needs something extra, [03:37.000 --> 03:40.000] one of the teams creates now services [03:40.000 --> 03:44.000] that we can use to make it more modular like that. [03:44.000 --> 03:49.000] So, why do we need to use this MySQL component? [03:49.000 --> 03:56.000] It's because the subsystem of these components [03:56.000 --> 04:02.000] is designed because there are some issues with the plugins. [04:02.000 --> 04:07.000] So, for example, the plugin can only talk to the server [04:07.000 --> 04:09.000] and not with other plugins. [04:09.000 --> 04:12.000] Here, with components, you could have some components [04:12.000 --> 04:14.000] talking to other components. [04:14.000 --> 04:17.000] That's something possible. [04:17.000 --> 04:21.000] The plugins, they have access to the server symbols [04:21.000 --> 04:25.000] and they can call them directly, but not really in consolation. [04:25.000 --> 04:28.000] And there are some, we were discussing that, [04:28.000 --> 04:32.000] that it is even possible maybe to create a component [04:32.000 --> 04:36.000] and compile it and then load it for another version of it. [04:36.000 --> 04:40.000] This is not something I would recommend to do, [04:40.000 --> 04:43.000] but it's possible. [04:43.000 --> 04:46.000] And you can also create these dependencies [04:46.000 --> 04:51.000] between components, which is very nice. [04:51.000 --> 04:54.000] So, we're going to create a component together. [04:54.000 --> 04:57.000] I will do it, but so you can see how it works [04:57.000 --> 05:03.000] and try to see, my plan is to show you that it's not complicated [05:03.000 --> 05:06.000] and that you will be able to create your own component. [05:06.000 --> 05:10.000] So, first thing, and this is for me, I think one of the most [05:10.000 --> 05:13.000] difficult parts when we want to extend MySQL is, [05:13.000 --> 05:17.000] oh, cool, I want to extend it, but what will I do? [05:17.000 --> 05:21.000] And sometimes on Slack or forums, I have people say, [05:21.000 --> 05:25.000] oh, I'm a young developer, I would like to help [05:25.000 --> 05:27.000] MySQL community. [05:27.000 --> 05:29.000] Yes? [05:29.000 --> 05:30.000] What? [05:30.000 --> 05:32.000] Yes, I need to say yes. [05:32.000 --> 05:34.000] Yeah, but why not? [05:34.000 --> 05:38.000] But people say, oh, I am learning C++ [05:38.000 --> 05:40.000] or I want to be in the MySQL community, [05:40.000 --> 05:45.000] I want to create something, and what could I do? [05:45.000 --> 05:47.000] That's the plan. [05:47.000 --> 05:51.000] You know, like Colin was telling earlier, [05:51.000 --> 05:55.000] we don't have like a list of features that we ask [05:55.000 --> 05:57.000] community to do. [05:57.000 --> 05:59.000] It's more that the community wants to enhance something, [05:59.000 --> 06:02.000] fix something, they will do it, right? [06:02.000 --> 06:05.000] So here, the most complicated is what will I do, [06:05.000 --> 06:09.000] how would I extend to your needs? [06:09.000 --> 06:11.000] So this is what we're going to define. [06:11.000 --> 06:14.000] So the first thing is that to be able to use what we're going [06:14.000 --> 06:17.000] to use, I want to have a specific privilege. [06:17.000 --> 06:20.000] So not everybody will be able to use the extension we're [06:20.000 --> 06:24.000] going to do, and I decided to use the sensitive variables [06:24.000 --> 06:28.000] observer privilege that was added in 8029. [06:28.000 --> 06:32.000] So you can also, if you want, it's create a new privilege [06:32.000 --> 06:34.000] for what you are doing. [06:34.000 --> 06:36.000] I've made, I don't know if you have seen, [06:36.000 --> 06:42.000] I create a component in 13 block posts with, [06:42.000 --> 06:44.000] was covering a lot of things to do it, [06:44.000 --> 06:46.000] and one of them was to create a privilege [06:46.000 --> 06:48.000] and use that privilege. [06:48.000 --> 06:52.000] Then we're going to read a value of some predefined [06:52.000 --> 06:56.000] variables on the server, and let's say, [06:56.000 --> 07:00.000] extract the pass of it, and then create a performance [07:00.000 --> 07:04.000] schema table with the path that we extracted from this [07:04.000 --> 07:08.000] variable, and see if there is free space and how many [07:08.000 --> 07:13.000] space has been used on this storage that related to the [07:13.000 --> 07:14.000] pass. [07:14.000 --> 07:17.000] So it's a simple, but it can be very useful that you [07:17.000 --> 07:21.000] don't need to have access as a DBA to the file system [07:21.000 --> 07:24.000] to check that. [07:24.000 --> 07:27.000] So to be able to do this, we will need, of course, [07:27.000 --> 07:33.000] to use several services that are to get the information [07:33.000 --> 07:37.000] from the privileges, so the security of the threads, [07:37.000 --> 07:40.000] to need to have access to the performance schema table [07:40.000 --> 07:43.000] to create one, to create the different fields, [07:43.000 --> 07:47.000] like here we're going to use the table, [07:47.000 --> 07:49.000] but we want to have some begin and stuff like that. [07:49.000 --> 07:53.000] We also need to have a log built-in to create error messages. [07:53.000 --> 07:56.000] We need to send message to the user, for example, [07:56.000 --> 07:59.000] oh, you don't have privilege to access this table, [07:59.000 --> 08:04.000] so we need to subscribe and to use all these services [08:04.000 --> 08:06.000] to do that. [08:06.000 --> 08:07.000] Yes. [08:11.000 --> 08:15.000] These are services, and I will show you how to do that, [08:15.000 --> 08:18.000] so you use these services and then you call them [08:18.000 --> 08:22.000] and you get the answer, and it's much easier than [08:22.000 --> 08:24.000] on the plug-in, for example. [08:26.000 --> 08:29.000] Yes, so the URL I was showing you earlier, [08:29.000 --> 08:32.000] it's the list of all the components that you can use [08:32.000 --> 08:34.000] and how to use them. [08:36.000 --> 08:40.000] So which variable are we going to check? [08:40.000 --> 08:46.000] So if you're a SQL DBA, you need how many variables [08:46.000 --> 08:48.000] define a path that you need to check? [08:48.000 --> 08:50.000] Do you have an ID? [08:50.000 --> 08:54.000] One, two, three, more, less. [08:56.000 --> 08:58.000] It's a quiz. [08:59.000 --> 09:01.000] It's a lot, and more and more. [09:01.000 --> 09:04.000] So, for example, we have lock bin base name. [09:04.000 --> 09:06.000] We should put the binary locks. [09:06.000 --> 09:08.000] We can put them somewhere. [09:08.000 --> 09:11.000] The data here, hopefully you know what it means. [09:11.000 --> 09:13.000] It is where the data will be. [09:13.000 --> 09:17.000] Temdir, you know, db-undo directory, you know, db-data-own. [09:17.000 --> 09:22.000] So all these can be different paths at a different part [09:22.000 --> 09:24.000] that we can store data, right? [09:24.000 --> 09:28.000] So we will need, I will use here a vector of the string [09:28.000 --> 09:30.000] and I will put all these variables in it. [09:30.000 --> 09:34.000] This is predefined because I know that this can be, [09:34.000 --> 09:37.000] if there is some value in these variables, [09:37.000 --> 09:39.000] I will check that. [09:39.000 --> 09:41.000] Of course, if you want, you can extend that [09:41.000 --> 09:44.000] and create, for example, a variable [09:44.000 --> 09:47.000] where you will put the name of the variables to list. [09:47.000 --> 09:48.000] It's possible. [09:48.000 --> 09:50.000] It's just depending on what you want to do that. [09:50.000 --> 09:54.000] And this is, for example, all you call, [09:54.000 --> 09:56.000] you want to register a new variable. [09:56.000 --> 10:00.000] For example, this variable, 2 par, I called, right? [10:00.000 --> 10:02.000] This is how you call the MySQL service components [10:02.000 --> 10:04.000] is variable register. [10:04.000 --> 10:08.000] And you register your variable. [10:08.000 --> 10:10.000] Okay? [10:10.000 --> 10:14.000] So let's go, we are in ACA conference, right? [10:14.000 --> 10:17.000] So our component will look like this. [10:17.000 --> 10:22.000] So we will, in the MySQL server source directory, [10:22.000 --> 10:24.000] there is a component folder. [10:24.000 --> 10:29.000] And in that folder, I will create my disk size component. [10:29.000 --> 10:31.000] So it's another folder. [10:31.000 --> 10:33.000] I will have a CMake list. [10:33.000 --> 10:36.000] And then a disk size, you see this size dot header [10:36.000 --> 10:43.000] and a disk size PFS where I put the stuff for a performance schema. [10:43.000 --> 10:45.000] If we have time, and I think we may have, [10:45.000 --> 10:47.000] I will just show you the content of the file. [10:47.000 --> 10:53.000] But before, I will show you what we have in this, [10:53.000 --> 10:55.000] some part of it, how to use it. [10:55.000 --> 10:59.000] So, for example, if you want to write in the error lock, [10:59.000 --> 11:04.000] all our component needs to have a tag. [11:04.000 --> 11:07.000] So I don't know if this will work. [11:07.000 --> 11:09.000] Seems not, oops. [11:09.000 --> 11:11.000] Where is it? [11:11.000 --> 11:13.000] Yeah. [11:13.000 --> 11:15.000] Yeah, it's with the, yeah. [11:15.000 --> 11:17.000] I need to be very slow. [11:17.000 --> 11:21.000] Very slow, yeah. [11:21.000 --> 11:23.000] You see here? [11:23.000 --> 11:25.000] It's not that useful. [11:25.000 --> 11:29.000] You can, you say lock component tag and it's disk size. [11:29.000 --> 11:35.000] So every error message that I will create will have this disk size [11:35.000 --> 11:37.000] tag in it. [11:37.000 --> 11:40.000] So I will require a service page. [11:40.000 --> 11:42.000] So I need to use the lock built-ins, [11:42.000 --> 11:46.000] lock built-in strings because I want to send strings, right? [11:46.000 --> 11:49.000] And this is the service type I will going to use. [11:49.000 --> 11:51.000] And I'm defining here. [11:51.000 --> 11:57.000] And then, for example, when I will initialize my component, right? [11:57.000 --> 12:05.000] I will here call this and initialize the lock objects. [12:05.000 --> 12:08.000] And when I just do lock component error, [12:08.000 --> 12:11.000] which type of error it is? [12:11.000 --> 12:13.000] Can you be warning? [12:13.000 --> 12:17.000] Here is information level, print message, initializing. [12:17.000 --> 12:21.000] Just so every time I will load the plugin, the component, [12:21.000 --> 12:22.000] I will have this. [12:22.000 --> 12:23.000] So this is how we do it. [12:23.000 --> 12:24.000] It's very easy. [12:24.000 --> 12:27.000] So this is some code that you will reuse all the time. [12:27.000 --> 12:32.000] And then in your component, this is the message if you want [12:32.000 --> 12:34.000] to print an error message. [12:34.000 --> 12:40.000] So usually it's much more easy than in a plugin. [12:40.000 --> 12:43.000] To check a privilege, so I create here a function [12:43.000 --> 12:45.000] F required privilege, right? [12:45.000 --> 12:48.000] And I will send the THD. [12:48.000 --> 12:52.000] And also to get the context, to get the security context of THD, [12:52.000 --> 12:54.000] all that, our services. [12:54.000 --> 13:00.000] And then we check, OK, do we have access to this privilege? [13:00.000 --> 13:03.000] And if not, I will say I will print an error. [13:03.000 --> 13:05.000] If it's OK, we can continue. [13:05.000 --> 13:07.000] So here we check the privilege. [13:07.000 --> 13:09.000] So this is how we do it. [13:09.000 --> 13:14.000] And it's quite very easy to do all that kind of stuff like this. [13:14.000 --> 13:18.000] And for example, if you want to access a global variable, [13:18.000 --> 13:23.000] it's also again, get the variable from this variable register, [13:23.000 --> 13:26.000] get the variable, put the name of the variable, [13:26.000 --> 13:29.000] and you will get the data out of it. [13:29.000 --> 13:31.000] So this is how it works. [13:31.000 --> 13:34.000] And it's quite very easy. [13:34.000 --> 13:36.000] And you can extend that. [13:36.000 --> 13:42.000] Like I said, there is 161 services to create performance [13:42.000 --> 13:48.000] to get information for plenty of stuff. [13:48.000 --> 13:50.000] So it is very, very easy. [13:50.000 --> 13:53.000] So how does it look like when we run this component, right? [13:53.000 --> 13:56.000] So the first thing we do, if you can read it, [13:56.000 --> 13:59.000] is we install the component. [13:59.000 --> 14:04.000] So we do install component and then file component disk size. [14:04.000 --> 14:08.000] By default, the components, they start with the name component underscore. [14:08.000 --> 14:11.000] But you can change that if you want. [14:11.000 --> 14:13.000] You can see it's okay. [14:13.000 --> 14:15.000] It means it has been loaded, right? [14:15.000 --> 14:17.000] If we check in the error lock, [14:17.000 --> 14:20.000] because remember we were printing initializing [14:20.000 --> 14:23.000] when we were loading the component, [14:23.000 --> 14:25.000] we will see because in Mexico, [14:25.000 --> 14:28.000] the error lock is also part of performance schema table. [14:28.000 --> 14:31.000] So you don't need to go a tail file. [14:31.000 --> 14:37.000] We can see that, okay, component disk size reported initializing, [14:37.000 --> 14:39.000] component disk size reported, [14:39.000 --> 14:42.000] performance schema table has been registered successfully. [14:42.000 --> 14:45.000] So all that information comes from the component [14:45.000 --> 14:47.000] and you can find it in the error lock. [14:47.000 --> 14:49.000] So that's the first thing. [14:49.000 --> 14:52.000] We were happy because we were able to load the component [14:52.000 --> 14:56.000] and we see that in error lock, the component is written. [14:56.000 --> 15:00.000] And then we can see also here to use it really. [15:00.000 --> 15:04.000] So we do select start from performance schema disk size, [15:04.000 --> 15:07.000] which is the performance schema table we created. [15:07.000 --> 15:13.000] So it gives us all the data, the directory or the path [15:13.000 --> 15:16.000] from which variable it comes from, right? [15:16.000 --> 15:22.000] And the free size and the total size invites from it. [15:22.000 --> 15:24.000] So this is quite very useful. [15:24.000 --> 15:27.000] So you can check without having to, [15:27.000 --> 15:29.000] after you can do whatever you want with this information, [15:29.000 --> 15:32.000] but it was to show something relevant [15:32.000 --> 15:34.000] and not just a yellow word to you guys. [15:34.000 --> 15:37.000] I think this is more useful. [15:37.000 --> 15:41.000] And for example, yeah, you can display or you can play [15:41.000 --> 15:45.000] with the new function like the format bytes and stuff. [15:45.000 --> 15:48.000] And you can see here the free size, total size, [15:48.000 --> 15:51.000] how many percent are used on the disk, [15:51.000 --> 15:54.000] depending where you want to check. [15:54.000 --> 15:58.000] What do you see here is that everything points on the same SSD [15:58.000 --> 16:01.000] on my laptop and this is why you have always the same numbers [16:01.000 --> 16:04.000] because at the end it's only the same disk. [16:04.000 --> 16:07.000] But if you use different disks, [16:07.000 --> 16:11.000] you will have different values here. [16:11.000 --> 16:14.000] The error, like I said earlier, I was using, [16:14.000 --> 16:20.000] we created this, we were using this specific privilege. [16:20.000 --> 16:24.000] So here I'm using another user, which is called Restore. [16:24.000 --> 16:25.000] I was for Dockstore. [16:25.000 --> 16:27.000] We were discussing about Dockstore earlier. [16:27.000 --> 16:30.000] So I want to check in the performance schema table [16:30.000 --> 16:33.000] with that user and you can see that user doesn't have [16:33.000 --> 16:35.000] the privilege we want. [16:35.000 --> 16:39.000] He says, OK, this select is denied because the user cannot, [16:39.000 --> 16:42.000] so I don't give access to the performance schema table [16:42.000 --> 16:46.000] to everybody, just some specific user. [16:46.000 --> 16:51.000] So some information about the MySQL components. [16:51.000 --> 16:56.000] It is, you can see which are the components that are loaded. [16:56.000 --> 16:59.000] So you do select start from MySQL component. [16:59.000 --> 17:02.000] So there is a system table called component [17:02.000 --> 17:07.000] and you can see which are the component loaded [17:07.000 --> 17:09.000] and sometimes a component can be part of a group [17:09.000 --> 17:16.000] and then you will see if they're on the same group or not, [17:16.000 --> 17:17.000] which is not the case here. [17:17.000 --> 17:19.000] But you can see here, I have several, [17:19.000 --> 17:22.000] so the query attribute is a component, for example. [17:22.000 --> 17:25.000] And then other component that I'm playing with on my system [17:25.000 --> 17:29.000] like UID, V7 and stuff like that, [17:29.000 --> 17:33.000] that you can create if you want. [17:33.000 --> 17:38.000] Where are these components on the disk? [17:38.000 --> 17:41.000] It's on the plugin here, same as the plugin. [17:41.000 --> 17:43.000] So you will see where the plugins are. [17:43.000 --> 17:46.000] You have also the components there [17:46.000 --> 17:49.000] and by default the name start with component. [17:49.000 --> 17:52.000] So the disk size, we just created it here, [17:52.000 --> 17:54.000] component disk size. [17:54.000 --> 17:57.000] And you can see there are several components already [17:57.000 --> 18:02.000] in MySQL by default [18:02.000 --> 18:10.000] because we are also using our own infrastructure in MySQL. [18:10.000 --> 18:13.000] So some question that I've heard about the component [18:13.000 --> 18:17.000] is that is it that when we load a component [18:17.000 --> 18:19.000] after we start of the server, [18:19.000 --> 18:20.000] what happens with that component? [18:20.000 --> 18:24.000] So all the components will be reloaded again, in fact. [18:24.000 --> 18:26.000] So if you install the component, [18:26.000 --> 18:28.000] when you restart, it will be installed. [18:28.000 --> 18:30.000] So there is no configuration in my CNF. [18:30.000 --> 18:33.000] You need to load it first and then it will stay loaded. [18:33.000 --> 18:39.000] Meaning that if I remove the component that was installed [18:39.000 --> 18:42.000] because I like to suffer, right? [18:42.000 --> 18:43.000] And what will happen? [18:43.000 --> 18:45.000] In fact, you will have a message that says, [18:45.000 --> 18:47.000] oh, this component, for example, [18:47.000 --> 18:50.000] cannot be open and there is an issue. [18:50.000 --> 18:51.000] But that's the only thing. [18:51.000 --> 18:52.000] It won't block the server. [18:52.000 --> 18:53.000] It won't crash. [18:53.000 --> 18:55.000] It will just tell you, OK, this is not there [18:55.000 --> 18:58.000] and it won't be available for you. [18:58.000 --> 19:00.000] So if you are interested, for example, [19:00.000 --> 19:04.000] to see the code, the full code of the component, [19:04.000 --> 19:06.000] it's on GitHub. [19:06.000 --> 19:09.000] So on my GitHub, MySQL component disk size, [19:09.000 --> 19:11.000] you can find it. [19:11.000 --> 19:14.000] And also now it's your turn. [19:14.000 --> 19:17.000] Please show me what you can do and what you can invent [19:17.000 --> 19:19.000] and what you can bring to MySQL [19:19.000 --> 19:22.000] because I think the component infrastructure [19:22.000 --> 19:27.000] is very something cool that you can use [19:27.000 --> 19:30.000] to add features to MySQL. [19:30.000 --> 19:34.000] And I hope that, Vinicius, you will change your next talk [19:34.000 --> 19:36.000] to a component for the next year [19:36.000 --> 19:39.000] and not as a plugin, right? [19:39.000 --> 19:41.000] So thank you very much for this. [19:41.000 --> 19:43.000] Share your love to MySQL on the social media. [19:43.000 --> 19:46.000] Join us on the community Slack, [19:46.000 --> 19:49.000] so where plenty of people are there to answer questions [19:49.000 --> 19:52.000] from development, consulting, [19:52.000 --> 19:55.000] plenty of people from around the world, [19:55.000 --> 19:58.000] not working for MySQL, but in the MySQL community, [19:58.000 --> 20:00.000] are also there to answer you. [20:00.000 --> 20:14.000] Do you have questions?