Patchwork [1,of,3,RFC,-V3] Header file for level 0 cmd server API

login
register
mail settings
Submitter Iulian Stana
Date July 25, 2013, 5:27 p.m.
Message ID <2cc0845928f01bf161cb.1374773265@doppler>
Download mbox | patch
Permalink /patch/1959/
State Deferred
Headers show

Comments

Iulian Stana - July 25, 2013, 5:27 p.m.
# HG changeset patch
# User Iulian Stana <julian.stana@gmail.com>
# Date 1374750370 -10800
#      Thu Jul 25 14:06:10 2013 +0300
# Node ID 2cc0845928f01bf161cb1d4983bd029c7c3e70aa
# Parent  0000000000000000000000000000000000000000
Header file for level 0 cmd server API

This patch includes just the header file of c-hglib API. (client.h)

This header is basically unchanged from the last patch,
(http://mercurial.markmail.org/thread/qsfwzmxzzs4ekuuv), but I am resubmitting
it as part of a wider work where I propose examples for some mercurial commands,
implemented in terms of these low level API (the "stories" that Matt asked for).

I made a page where I collected all the address questions.
(http://mercurial.selenic.com/wiki/C-Hglib/Questions)
The most important being: 'how do you get exit codes' and 'how do you treat
filenames w/ spaces'.

The "level 0", called also the raw level stands for the lowest level of c-glib.
The main idea is to "pass a raw command string, get unparsed results". Also to
create all the functions that will be needed on higher levels.
Now, we don't really get "unparse results", we _do_ parse the stdout of cmdsrv,
since we identify the channel type.
Laurens Holst - Aug. 6, 2013, 12:43 p.m.
Op 06-08-13 14:20, Iulian Stana schreef:
>
>     > +
>     > +/*
>     > + * Close the connection for the given handle.
>     > + * Erase the handle and free the memory
>     > + * \param handle The handle of the connection that I want to close
>     > + * \return   0 if successful
>     > + *          -1 to indicate an error, with errno set appropriately.
>     > + * errno can be:
>     > + *      EINVAL
>     > + * */
>     > +int hg_close(hg_handle **handle);
>
>     One '*' too many, unless you're planning on closing multiple
>     handles at once...
>
>
> It's a defense action, I need to set the pointer to NULL, to be sure 
> that there will
> be no other calls after hg_close. (We can assume that our users will 
> not make
> this kind of action, then I will change to only one '*')

That does not help if the handle is also in another variable (e.g. of a 
calling function).

I do think it's smart to defend against this, but it's better prevented 
by always handing out unique handles that will cause an error if reused 
after closing.

~Laurens

Patch

diff --git a/client.h b/client.h
new file mode 100644
--- /dev/null
+++ b/client.h
@@ -0,0 +1,149 @@ 
+#ifndef _CLIENT_H_
+#define _CLIENT_H_
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+
+/*
+ * This structure contains the variables for the header.
+ * The channel will stock a letter that will indicate the type of channel.
+ * The length will stock the size of data that will be send or the maxim data
+ * that can be received by the server.
+ * */
+typedef struct hg_header{
+    char channel;
+    uint32_t length;
+} hg_header;
+
+/*
+ * This structure will be use the handle the connection with the server.
+ * He contains 2 pipes for the biderectional connection.
+ * The childpid, the pid of the process that will open the connection.
+ * The header that will contain the current header-action(channel, length). 
+ */
+typedef struct hg_handle{
+    pid_t childpid;
+    hg_header header;
+    int p_read;
+    int p_write;
+
+} hg_handle;
+
+
+/*
+ * Open the connection with the mecurial command server.
+ * The handle structure will be allocated.
+ * \param path The path to the repository wherewith I want to create a connection
+ *        NULL argument means the repository in which I am.
+ * \param encoding Will set HGENCODING to the given encoding
+ *        NULL argument means the default encoding. (UTF-8)
+ * \return A handle for this connection. 
+ *        NULL to indicate an error, with errno set appropriately.
+ * errno can be :
+ *      ECONNREFUSED
+ *      EFAULT - for a bad path address
+ *      EINVAL - for a bad encoding
+ *      All the errors that can be provide from exec
+ * */
+hg_handle *hg_open(const char *path, char *encoding);
+
+/*
+ * Close the connection for the given handle.
+ * Erase the handle and free the memory
+ * \param handle The handle of the connection that I want to close
+ * \return   0 if successful
+ *          -1 to indicate an error, with errno set appropriately.
+ * errno can be:
+ *      EINVAL
+ * */
+int hg_close(hg_handle **handle);
+
+/*
+ * Sending a command to the mercurial command server, through the given handle.
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \param command An array of pointers to null-terminated strings that represent
+ *                the argument list available to the new command.
+ * \param cmd_size The length of command array.
+ * \return   0 if successful
+ *          -1 to indicate an error, with errno set appropriately.
+ * errno can be:
+ *      EINVAL
+ *      EIO
+ *      ECOMM
+ * */
+int hg_rawcommand(hg_handle *handle, char *const command[], size_t cmd_size);
+
+/*
+ * Reading some unparse data from the server. Will read just a 'line', the 
+ * header that is received from server and the data that comes after the header
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \param buffer A character array where the read content will be stored.
+ * \param sizebuff The number of bytes to read.
+ * \return   The number of bytes that were read.
+ *          -1 to indicate an error, with errno set appropriately.
+ * errno can be:
+ *      EINVAL
+ *      EIO
+ *      ECOMM
+ * */
+int hg_rawread(hg_handle *handle, char *buffer, size_t sizebuff);
+
+/*
+ * Will write the buffer to server for the connection establish by the handle.
+ * This function will be used when one of the input channels will be received 
+ * from the command server. ('I' or 'L' channels)
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \param buffer A null terminated character string of the content to write.
+ * \param sizebuff The number of bytes to write 
+ * \return   The number of bytes that were written
+ *          -1 to indicate an error, with errno set appropriately.
+ * errno can be:
+ *      EINVAL
+ *      EIO
+ *      ECOMM
+ * */
+int hg_rawwrite(hg_handle *handle, const char *buffer, size_t sizebuff);
+
+/*
+ * Before you read or write data, you will want to know for what kind of data is 
+ * server waiting, an input data or an output data.
+ * This function will return the current channel for the connection established
+ * by the handle.
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \return   0 if successful
+ *          -1 to indicate an error, with errno set appropriately.
+ * errno can be:
+ *      EINVAL
+ *      EIO
+ *      ECOMM
+ * */
+char hg_channel(hg_handle *handle);
+
+/*
+ * Sometimes, the user needs the entire header. This is a way to do that.
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \return  The hader stucture for the given handle.
+ *          NULL to indicate an error, with errno set appropriately.
+ * errno can be:
+ *      EINVAL
+ * */
+hg_header hg_head(hg_handle *handle);
+
+/*
+ * The server tell use that he finished his action when the 'r' channel is send.
+ * This function will get the exitcode from the server, in as a measure to tell
+ * that the command was finished.
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \return   exitcode if successful
+ *          -1 to indicate an error, with errno set appropriately.
+ * errno can be:
+ *      EINVAL
+ *      EIO
+ *      ECOMM
+ * */
+int hg_exitcode(hg_handle *handle);
+
+#endif
+