2324
|
1 #include "config.h"
|
|
2
|
2322
|
3 #ifdef USE_STREAM_CACHE
|
|
4 // gcc cache2.c ../linux/shmem.o -o cache2
|
|
5
|
|
6 // Initial draft of my new cache system...
|
|
7 // includes some simulation code, using usleep() to emulate limited bandwith
|
|
8 // TODO: seeking, data consistency checking
|
|
9
|
|
10 #define READ_SPEED 20
|
|
11 #define FILL_SPEED 10
|
|
12
|
|
13 #include <stdio.h>
|
|
14 #include <stdlib.h>
|
|
15 #include <string.h>
|
|
16 #include <signal.h>
|
|
17
|
|
18 #include "../linux/shmem.h"
|
|
19
|
|
20 #include "stream.h"
|
|
21
|
|
22 int stream_fill_buffer(stream_t *s);
|
|
23 int stream_seek_long(stream_t *s,off_t pos);
|
|
24
|
|
25
|
|
26 typedef struct {
|
|
27 // constats:
|
|
28 unsigned char *buffer; // base pointer of the alllocated buffer memory
|
|
29 int buffer_size; // size of the alllocated buffer memory
|
|
30 int sector_size; // size of a single sector (2048/2324)
|
|
31 // Note: buffer_size should be N*sector_size, where N is integer...
|
|
32 int back_size; // we should keep back_size amount of old bytes for backward seek
|
|
33 int fill_limit; // we should fill buffer if space>fill_limit
|
|
34 // reader's pointers:
|
|
35 int read_filepos;
|
|
36 // filler's pointers:
|
|
37 int min_filepos; // buffer contain only a part of the file, from min-max pos
|
|
38 int max_filepos;
|
|
39 int offset; // filepos <-> bufferpos offset value (filepos of the buffer's first byte)
|
|
40 // commands/locking:
|
|
41 int cmd_lock; // 1 if we will seek/reset buffer, 2 if we are ready for cmd
|
|
42 int fifo_flag; // 1 if we should use FIFO to notice cache about buffer reads.
|
|
43 // callback
|
|
44 stream_t* stream;
|
|
45 } cache_vars_t;
|
|
46
|
|
47 int min_fill=0;
|
|
48 int sleep_flag=0;
|
|
49
|
|
50 void cache_stats(cache_vars_t* s){
|
|
51 int newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
|
|
52 printf("0x%06X [0x%06X] 0x%06X ",s->min_filepos,s->read_filepos,s->max_filepos);
|
|
53 printf("%3d %% (%3d%%)\n",100*newb/s->buffer_size,100*min_fill/s->buffer_size);
|
|
54 }
|
|
55
|
|
56 int cache_read(cache_vars_t* s,unsigned char* buf,int size){
|
|
57 int total=0;
|
|
58 while(size>0){
|
|
59 int pos,newb,len;
|
|
60
|
|
61 pos=s->read_filepos - s->offset;
|
|
62 if(pos<0) pos+=s->buffer_size; else
|
|
63 if(pos>=s->buffer_size) pos-=s->buffer_size;
|
|
64
|
|
65 newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
|
|
66
|
|
67 if(newb<min_fill) min_fill=newb; // statistics...
|
|
68
|
|
69 if(newb<=0){
|
|
70 // waiting for buffer fill...
|
|
71 usleep(10000); // 10ms
|
|
72 continue;
|
|
73 }
|
|
74
|
|
75 // printf("*** newb: %d bytes ***\n",newb);
|
|
76
|
|
77 if(newb>s->buffer_size-pos) newb=s->buffer_size-pos; // handle wrap...
|
|
78 if(newb>size) newb=size;
|
|
79
|
|
80 // len=write(mem,newb)
|
|
81 //printf("Buffer read: %d bytes\n",newb);
|
|
82 memcpy(buf,&s->buffer[pos],newb);
|
|
83 buf+=newb;
|
|
84 len=newb; //usleep(len*READ_SPEED*sleep_flag);
|
|
85 // ...
|
|
86
|
|
87 s->read_filepos+=len;
|
|
88 size-=len;
|
|
89 total+=len;
|
|
90
|
|
91 }
|
|
92 return total;
|
|
93 }
|
|
94
|
|
95 int cache_fill(cache_vars_t* s){
|
|
96 int read,back,newb,space,len,pos,endpos;
|
|
97
|
|
98 read=s->read_filepos;
|
|
99
|
|
100 // calc number of back-bytes:
|
|
101 back=read - s->min_filepos;
|
|
102 if(back<0) back=0; // strange...
|
|
103 if(back>s->back_size) back=s->back_size;
|
|
104
|
|
105 // calc number of new bytes:
|
|
106 newb=s->max_filepos - read;
|
|
107 if(newb<0) newb=0; // strange...
|
|
108
|
|
109 // calc free buffer space:
|
|
110 space=s->buffer_size - (newb+back);
|
|
111
|
|
112 // calc bufferpos:
|
|
113 pos=s->max_filepos - s->offset;
|
|
114 if(pos>=s->buffer_size) pos-=s->buffer_size; // wrap-around
|
|
115
|
|
116 if(space<s->fill_limit){
|
|
117 // printf("Buffer is full (%d bytes free, limit: %d)\n",space,s->fill_limit);
|
|
118 return 0; // no fill...
|
|
119 }
|
|
120
|
|
121 // printf("### read=0x%X back=%d newb=%d space=%d pos=%d\n",read,back,newb,space,pos);
|
|
122
|
|
123 // reduce space if needed:
|
|
124 if(space>s->buffer_size-pos) space=s->buffer_size-pos;
|
|
125
|
|
126 // if(space>32768) space=32768; // limit one-time block size
|
|
127 if(space>4*s->sector_size) space=4*s->sector_size;
|
|
128
|
|
129 s->min_filepos=read-back; // avoid seeking-back to temp area...
|
|
130
|
|
131 // ....
|
|
132 //printf("Buffer fill: %d bytes of %d\n",space,s->buffer_size);
|
|
133 //len=space; usleep(len*FILL_SPEED*sleep_flag);
|
|
134 //len=stream_fill_buffer(s->stream);
|
|
135 //memcpy(&s->buffer[pos],s->stream->buffer,len); // avoid this extra copy!
|
|
136 // ....
|
|
137 stream_read(s->stream,&s->buffer[pos],space); len=space;
|
|
138
|
|
139 s->max_filepos+=len;
|
|
140 if(pos+len>=s->buffer_size){
|
|
141 // wrap...
|
|
142 s->offset+=s->buffer_size;
|
|
143 }
|
|
144
|
|
145 return len;
|
|
146
|
|
147 }
|
|
148
|
|
149 cache_vars_t* cache_init(int size,int sector){
|
|
150 int num;
|
|
151 cache_vars_t* s=shmem_alloc(sizeof(cache_vars_t));
|
|
152 memset(s,0,sizeof(cache_vars_t));
|
|
153 num=size/sector;
|
|
154 s->buffer_size=num*sector;
|
|
155 s->sector_size=sector;
|
|
156 s->buffer=shmem_alloc(s->buffer_size);
|
|
157 s->fill_limit=8*sector;
|
|
158 s->back_size=size/2;
|
|
159 return s;
|
|
160 }
|
|
161
|
|
162 static void exit_sighandler(int x){
|
|
163 // close stream
|
|
164 exit(0);
|
|
165 }
|
|
166
|
|
167 void stream_enable_cache(stream_t *s,int size){
|
|
168 int ss=(s->type==STREAMTYPE_VCD)?VCD_SECTOR_DATA:STREAM_BUFFER_SIZE;
|
|
169 s->cache_data=cache_init(size,ss);
|
|
170 ((cache_vars_t*)s->cache_data)->stream=s; // callback
|
|
171 if((s->cache_pid=fork())) return; // parent exits
|
|
172 // cache thread mainloop:
|
|
173 signal(SIGTERM,exit_sighandler); // kill
|
|
174 while(1){
|
|
175 if(!cache_fill(s->cache_data)){
|
|
176 usleep(50000); // idle
|
|
177 }
|
2327
|
178 // cache_stats(s->cache_data);
|
2322
|
179 }
|
|
180 }
|
|
181
|
|
182 int cache_stream_fill_buffer(stream_t *s){
|
|
183 int len;
|
|
184 if(s->eof){ s->buf_pos=s->buf_len=0; return 0; }
|
|
185 if(!s->cache_pid) return stream_fill_buffer(s);
|
|
186
|
2327
|
187 cache_stats(s->cache_data);
|
|
188
|
2322
|
189 len=cache_read(s->cache_data,s->buffer, ((cache_vars_t*)s->cache_data)->sector_size);
|
2327
|
190
|
2322
|
191 if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; }
|
|
192 s->buf_pos=0;
|
|
193 s->buf_len=len;
|
|
194 s->pos+=len;
|
|
195 // printf("[%d]",len);fflush(stdout);
|
|
196 return len;
|
|
197
|
|
198 }
|
|
199
|
|
200 int cache_stream_seek_long(stream_t *s,off_t pos){
|
|
201
|
|
202 if(!s->cache_pid) return stream_seek_long(s,pos);
|
|
203
|
|
204 printf("cache2 seek not implemented!!!!!!!!\n");
|
|
205 return 0;
|
|
206 }
|
|
207
|
|
208 #endif
|