Re: [GSoC] Questions about project Text-Extraction Libraries
Bruno Baruffaldi <[email protected]> Sat, 23 Mar 2019 15:42:36 -0300
| Newsgroups | gmane.comp.search.xapian.devel |
|---|---|
| Message-ID | <CAND-c9OXOFKdJfAbuAvkiKpS33BF02HGiza14uuxG=WJkKOX2w@mail.gmail.com> |
--0000000000008c5b1b0584c756c5 Content-Type: multipart/alternative; boundary="0000000000008c5b120584c756c3" --0000000000008c5b120584c756c3 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Thanks! That was really useful! I wanted to share my approach to this project with the hope that you can give me some feedback. I am think that applying a design that foresees the incorporation of new file formats is the most suitable way to solve the problem. In the attached sketch we can see: * Bug_Box: It is responsible for encapsulating and handling errors. * File_extrator: It presents an interface for the different formats. * File_X: Encapsulates a particular library for the X file format. * File_Hadle: It is responsible for directing the extraction. More specifically, it determines the file format and which extractor to use. * Ominex: It represents the rest of the project. The idea of organizing the code in this way focuses on two fundamental items: * The possibility of changing a particular library for another that fulfills the same purpose without affecting the project. * The possibility of extending Xapian's support in terms of file format. One of the major advantages is that if a particular programmer wishes to add support for a new file format or improve an existing one, they should only modify the objects that are in red. In this way, with a proper documentation this kind of tasks should not be a complex task. I know it is an ambitious approach, but I think that with a good documentation it would give the project great flexibility and the programmers would have the option of adapting Xapian to their needs. **The image only presents a simple scheme to explain the idea, I do not consider it as a design for the project. I believe that we should discuss about different design patterns to choose the most suitable one. Cheers, Bruno Baruffaldi El s=C3=A1b., 23 de mar. de 2019 a la(s) 12:10, Olly Betts ([email protected]= ) escribi=C3=B3: > On Thu, Mar 21, 2019 at 09:31:26AM -0300, Bruno Baruffaldi wrote: > > Firstly, I think that trying to isolate library bugs in subprocesses > could > > get to work, but I am not sure about how to handle deadlocks or infinit= e > > loops. I feel that using a timer is the only way to deal with it but I > > would like to know what you think about it. > > There's already code to set a CPU time limit for filter subprocesses > (using setrlimit()) and to implement an inactivity timeout (by using > select() to wait for the connection file descriptor to become readable > or a timeout to be reached) - see runfilter.cc. I think both mechanisms > should be usable for this project (the CPU time limit would need to > allow for CPU time used by the child process processing previous > files). > > > Secondly, I have been reading the source code of ominex, but I cannot > > figure out if it is possible to group all file formats under the same > > interface. When indexing files, are all file formats treated in a simil= ar > > way, or are there special formats that require a different work (beyond > the > > use of external filters)? > > A few do - e.g. for PDF files we currently need to run pdfinfo and > pdftotext on the file, PostScript files are first converted to a > temporary PDF (because there doesn't seem to be a Unicode-aware > filter which converts PostScript to text), etc. > > It may be possible to come up with a common interface still though. > > > To sum up, I want to know if ominex use multithreading for indexing fil= es > > or if you consider that it could be implemented to speed it up. > > Currently there isn't really any parallelism in omindex. It would help > when indexing formats which are CPU intensive to extract text from > (an extreme case is if you're running OCR to index image files). > > When dealing with external filters, the extra isolation that > subprocesses gives us makes that a better approach than launching > threads - if a library used by a thread crashes the process then the > indexer dies, while if that happens in a subprocess the parent indexer > process can recover easily. > > Potentially we could have concurrent child processes working on > different documents. I'd suggest that it's better to focus on getting > the subprocesses to work individually first before trying to get them to > run in parallel, but to keep in mind that we're likely to want to > instantiate multiple concurrent instances while implementing them. > > --=20 Atte. Bruno Baruffaldi --0000000000008c5b120584c756c3 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div dir=3D"ltr"><div class=3D"gmail_default" style=3D"fon= t-family:tahoma,sans-serif">Thanks!<br>That was really useful!<br><br>I wan= ted to share my approach to this project with the hope that you can give me= some feedback.<br><br>I am think that applying a design that foresees the = incorporation of new file formats is the most suitable way to solve the pro= blem.<br><br>In the attached sketch we can see:<br>* Bug_Box: It is respons= ible for encapsulating and handling errors.<br>* File_extrator: It presents= an interface for the different formats.<br>* File_X: Encapsulates a partic= ular library for the X file format.<br>* File_Hadle: It is responsible for = directing the extraction. More specifically, it determines the file format = and which extractor to use.<br>* Ominex: It represents the rest of the proj= ect.<br><br>The idea of organizing the code in this way focuses on two fund= amental items:<br>* The possibility of changing a particular library for an= other that fulfills the same purpose without affecting the project.<br>* Th= e possibility of extending Xapian's support in terms of file format.<br= ><br>One of the major advantages is that if a particular programmer wishes = to add support for a new file format or improve an existing one, they shoul= d only modify the objects that are in red. In this way, with a proper docum= entation this kind of tasks should not be a complex task.<br><br>I know it = is an ambitious approach, but I think that with a good documentation it wou= ld give the project great flexibility and the programmers would have the op= tion of adapting Xapian to their needs.<br><br>**The image only presents a = simple scheme to explain the idea, I do not consider it as a design for the= project. I believe that we should discuss about different design patterns = to choose the most suitable one.<br><br>Cheers,<br>=C2=A0=C2=A0 Bruno Baruf= faldi<br><br></div></div></div><br><div class=3D"gmail_quote"><div dir=3D"l= tr" class=3D"gmail_attr">El s=C3=A1b., 23 de mar. de 2019 a la(s) 12:10, Ol= ly Betts (<a href=3D"mailto:[email protected]">[email protected]</a>) escribi= =C3=B3:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px = 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Thu, = Mar 21, 2019 at 09:31:26AM -0300, Bruno Baruffaldi wrote:<br> > Firstly, I think that trying to isolate library bugs in subprocesses c= ould<br> > get to work, but I am not sure about how to handle deadlocks or infini= te<br> > loops. I feel that using a timer is the only way to deal with it but I= <br> > would like to know what you think about it.<br> <br> There's already code to set a CPU time limit for filter subprocesses<br= > (using setrlimit()) and to implement an inactivity timeout (by using<br> select() to wait for the connection file descriptor to become readable<br> or a timeout to be reached) - see runfilter.cc.=C2=A0 I think both mechanis= ms<br> should be usable for this project (the CPU time limit would need to<br> allow for CPU time used by the child process processing previous<br> files).<br> <br> > Secondly, I have been reading the source code of ominex, but I cannot<= br> > figure out if it is possible to group all file formats under the same<= br> > interface. When indexing files, are all file formats treated in a simi= lar<br> > way, or are there special formats that require a different work (beyon= d the<br> > use of external filters)?<br> <br> A few do - e.g. for PDF files we currently need to run pdfinfo and<br> pdftotext on the file, PostScript files are first converted to a<br> temporary PDF (because there doesn't seem to be a Unicode-aware<br> filter which converts PostScript to text), etc.<br> <br> It may be possible to come up with a common interface still though.<br> <br> > To sum up, I want to know if ominex use multithreading for indexing fi= les<br> > or if you consider that it could be implemented to speed it up.<br> <br> Currently there isn't really any parallelism in omindex.=C2=A0 It would= help<br> when indexing formats which are CPU intensive to extract text from<br> (an extreme case is if you're running OCR to index image files).<br> <br> When dealing with external filters, the extra isolation that<br> subprocesses gives us makes that a better approach than launching<br> threads - if a library used by a thread crashes the process then the<br> indexer dies, while if that happens in a subprocess the parent indexer<br> process can recover easily.<br> <br> Potentially we could have concurrent child processes working on<br> different documents.=C2=A0 I'd suggest that it's better to focus on= getting<br> the subprocesses to work individually first before trying to get them to<br= > run in parallel, but to keep in mind that we're likely to want to<br> instantiate multiple concurrent instances while implementing them.<br> <br> </blockquote></div><br clear=3D"all"><br>-- <br><div dir=3D"ltr" class=3D"g= mail_signature"><div dir=3D"ltr">Atte. Bruno Baruffaldi<br></div></div> --0000000000008c5b120584c756c3-- --0000000000008c5b1b0584c756c5 Content-Type: image/png; name="sketch.png" Content-Disposition: attachment; filename="sketch.png" Content-Transfer-Encoding: base64 Content-ID: <f_jtlu97ds0> X-Attachment-Id: f_jtlu97ds0 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 AAAASUVORK5CYII= --0000000000008c5b1b0584c756c5--