summaryrefslogtreecommitdiffstats
path: root/src/squeue
diff options
context:
space:
mode:
authorpancake <pancake@dazo>2008-03-05 18:38:42 +0100
committerpancake <pancake@dazo>2008-03-05 18:38:42 +0100
commit2ddb2923c68d023f9733fb82bb8d28140ea5b695 (patch)
tree706162ce4107ec1444870ad4945a9e6d5a0cde91 /src/squeue
parent32a59f4279e1d72abc2b60f08d6e32e2a0b32478 (diff)
download0xFFFF-2ddb2923c68d023f9733fb82bb8d28140ea5b695.tar.bz2
* Initial import of the GtkAML gui frontend - Mostly implemented in just one night :)
* Import the squeue c and vapi sources * Make 0xFFFF run as squeue daemon with -Q flag * Up to 0.4
Diffstat (limited to 'src/squeue')
-rw-r--r--src/squeue/squeue.c250
-rw-r--r--src/squeue/squeue.h27
-rw-r--r--src/squeue/squeue.vapi43
3 files changed, 320 insertions, 0 deletions
diff --git a/src/squeue/squeue.c b/src/squeue/squeue.c
new file mode 100644
index 0000000..0386784
--- /dev/null
+++ b/src/squeue/squeue.c
@@ -0,0 +1,250 @@
+#include "squeue.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ipc.h>
+#include <signal.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+#define POOL_SIZE ITEM_MAX*ITEM_SIZE
+#define ITEM_SIZE 80
+#define ITEM_MAX 10
+
+int squeue_release(const char *file)
+{
+ int shmid;
+ key_t k = ftok(file, 0xa3);
+
+ if (k == -1) {
+ perror("ftok");
+ return -1;
+ }
+
+ shmid = shmget(k, POOL_SIZE, 0666);
+ if (shmid == -1)
+ return -1; // not released
+ return shmctl(shmid, IPC_RMID,NULL);
+}
+
+struct squeue_t *squeue_open(const char *file, int mode)
+{
+ struct squeue_t *q;
+ char *pool;
+ int shmid;
+ key_t k = ftok(file, 0xa3);
+_retry:
+ shmid = shmget(k, POOL_SIZE, 0666);
+ if (shmid == -1) {
+ if (mode == Q_WAIT) {
+ usleep(200);
+ goto _retry;
+ }
+ shmid = shmget(k, POOL_SIZE, 0666|IPC_EXCL|((mode==Q_CREAT)?IPC_CREAT:0));
+ if (shmid == -1) {
+ if (mode == Q_WAIT) {
+ usleep(200);
+ goto _retry;
+ }
+ perror("shmget");
+ return NULL;
+ }
+ }
+
+ if (mode == Q_WAIT)
+ mode = Q_OPEN;
+
+ pool = shmat(shmid, NULL, k);
+ if (((int)pool) == -1) {
+ perror("shmat\n");
+ return NULL;
+ }
+
+ if (mode == Q_CREAT)
+ memset(pool, '\0', POOL_SIZE);
+
+ q = (struct squeue_t *)malloc(sizeof(struct squeue_t));
+ memset(q, '\0', sizeof(struct squeue_t));
+ q->shmid = shmid;
+ q->pool = pool;
+ q->mode = mode;
+
+ return q;
+}
+
+void squeue_free(struct squeue_t *q)
+{
+ free(q);
+}
+
+int squeue_close(struct squeue_t *q)
+{
+ char *pool;
+
+ if (q==NULL)
+ return -1;
+
+ pool = q->pool;
+ shmctl(q->shmid, IPC_RMID, NULL);
+ free(q);
+ return shmdt(pool);
+}
+
+int squeue_push(struct squeue_t *q, const char *str, int lock)
+{
+ int i;
+
+ if (q==NULL)
+ return -1;
+// if (q->mode == Q_CREAT) {
+// printf("squeue_push: cannot push from the creator\n");
+// return -1;
+// }
+
+ if (str==NULL||strlen(str)>ITEM_SIZE)
+ return -1;
+ do {
+ if (q->squeue_idx >= ITEM_MAX) {
+ while (q->pool[0]!='\0') {
+ q->squeue_locks++;
+ if (!lock) {
+ printf("buffer is full\n");
+ return -1;
+ }
+ usleep(200);
+ }
+ q->squeue_idx = 0;
+ }
+
+ for(i=q->squeue_idx*ITEM_SIZE;i<POOL_SIZE;i+=ITEM_SIZE) {
+ if (q->pool[i]=='\0') {
+ strcpy(q->pool+i, str);
+ q->squeue_idx++;
+ return 1;
+ }
+ }
+ q->squeue_locks++;
+ } while (lock);
+ q->squeue_lost++;
+
+ return 0;
+}
+
+int squeue_pop(struct squeue_t *q)
+{
+ int i;
+ int two = 1;
+
+ if (q==NULL)
+ return -1;
+// if (q->mode == Q_OPEN) { // cannot pop when not owner of squeue
+// fprintf(stderr, "squeue_pop: cannot pop when you are not owner.\n");
+// return -1;
+// }
+ for(two=1;two--;q->head_idx = 0)
+ for(i=q->head_idx*ITEM_SIZE;i<POOL_SIZE;i+=ITEM_SIZE) {
+ if (q->pool[i]!='\0') {
+ q->pool[i]='\0';
+ q->head_idx++;
+ q->squeue_pops++;
+ return 1;
+ }
+ }
+ q->squeue_oops++;
+ fprintf(stderr, "WARNING: race condition detected in squeue.\n");
+ return 0;
+}
+
+char *squeue_get(struct squeue_t *q, int lock)
+{
+ int i=0;
+ int two = 1;
+
+ if(q==NULL)
+ return NULL;
+// if (q->mode == Q_OPEN) { // cannot pop when not owner of squeue
+// fprintf(stderr, "squeue_get: cannot pop when you are not owner.\n");
+// return NULL;
+// }
+ do {
+ for(two=1;two--;q->head_idx = 0) {
+ for(i=q->head_idx*ITEM_SIZE;i<POOL_SIZE;i+=ITEM_SIZE)
+ if (q->pool[i]!='\0')
+ return q->pool+i;
+ }
+ if (lock)
+ usleep(500);
+ } while (lock);
+ return NULL;
+}
+
+void squeue_stats(struct squeue_t *q)
+{
+ if(q==NULL)
+ return;
+ printf("Queue locks: %d\n", q->squeue_locks);
+ printf("Queue lost: %d\n", q->squeue_lost);
+ printf("Queue oops: %d\n", q->squeue_oops);
+ printf("Queue pops: %d\n", q->squeue_pops);
+}
+
+#if _MAIN_
+struct squeue_t *q;
+
+int sigc()
+{
+ squeue_stats(q);
+ exit(1);
+}
+
+int main()
+{
+ char buf[102];
+ int i;
+ int pid;
+
+ signal(SIGINT, sigc);
+
+ squeue_release("/dev/null");
+
+ pid = fork();
+ if (pid) {
+ q = squeue_open("/dev/null", Q_CREAT);
+ if (q == NULL) {
+ perror("oops");
+ kill(pid, SIGINT);
+ return;
+ }
+ squeue_push(q, "Hello World", 0);
+ squeue_push(q, "jeje msg 2", 0);
+
+ while(1) {
+ char *uh = squeue_get(q,1);
+ if (uh) {
+ printf("get: (%s)\n", uh);
+ squeue_pop(q);
+ }
+ usleep(200);
+ }
+ squeue_close(q);
+ } else {
+ q = squeue_open("/dev/null", Q_WAIT);
+ if (q == NULL) {
+ perror("oops");
+ return;
+ }
+ for(i=0;i<128;i++) {
+ sprintf(buf, "puta%d", i);
+ squeue_push(q, buf, 1);
+ usleep(100);
+ }
+ squeue_stats(q);
+ printf("cya\n");
+ squeue_close(q);
+ }
+
+ return 0;
+}
+#endif
diff --git a/src/squeue/squeue.h b/src/squeue/squeue.h
new file mode 100644
index 0000000..4730e3d
--- /dev/null
+++ b/src/squeue/squeue.h
@@ -0,0 +1,27 @@
+struct squeue_t {
+ int shmid;
+ int mode;
+ char *pool;
+ /* pointers */
+ int head_idx;
+ int squeue_idx;
+ /* counters */
+ int squeue_locks;
+ int squeue_lost;
+ int squeue_oops;
+ int squeue_pops;
+};
+
+
+#define Q_OPEN 0
+#define Q_CREAT 1
+#define Q_WAIT 2
+
+int squeue_release(const char *file);
+struct squeue_t *squeue_open(const char *file, int init);
+int squeue_close(struct squeue_t *q);
+void squeue_free(struct squeue_t *q);
+int squeue_push(struct squeue_t *q, const char *str, int lock);
+int squeue_pop(struct squeue_t *q);
+char *squeue_get(struct squeue_t *q, int lock);
+void squeue_stats(struct squeue_t *q);
diff --git a/src/squeue/squeue.vapi b/src/squeue/squeue.vapi
new file mode 100644
index 0000000..b8d82d4
--- /dev/null
+++ b/src/squeue/squeue.vapi
@@ -0,0 +1,43 @@
+using GLib;
+
+[CCode (lower_case_cprefix = "squeue_", cheader_filename = "squeue.h")]
+namespace SQueues {
+ [CCode (cname = "struct squeue_t", free_function = "squeue_free")]
+ public struct SQueue {
+ int shmid;
+ int mode;
+ char *pool;
+ /* pointers */
+ int head_idx;
+ int queue_idx;
+ /* counters */
+ int locks;
+ int lost;
+ int oops;
+ int pops;
+ [CCode (cname = "squeue_open")]
+ public static SQueue* open(string file, int mode);
+ [CCode (cname = "squeue_push")]
+ public int push(string msg, int l);
+ [CCode (cname = "squeue_get")]
+ public weak string get(int l);
+ [CCode (cname = "squeue_pop")]
+ public int pop();
+ [CCode (cname = "squeue_stats")]
+ public int stats();
+ [CCode (cname = "squeue_close")]
+ public int close();
+ [CCode (cname = "squeue_free")]
+ public int free();
+ [CCode (cname = "squeue_release")]
+ public static int release(string file);
+
+ }
+
+ [CCode (cprefix = "Q_", cheader_fileneme = "squeue.h")]
+ public enum SQueueMode {
+ OPEN = 0,
+ CREAT = 1,
+ WAIT = 2
+ }
+}