• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Konsole

BlockArray.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of Konsole, an X terminal.
00003     Copyright 2000 by Stephan Kulow <coolo@kde.org>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018     02110-1301  USA.
00019 */
00020 
00021 // Own
00022 #include "BlockArray.h"
00023 
00024 // System
00025 #include <assert.h>
00026 #include <sys/mman.h>
00027 #include <sys/param.h>
00028 #include <unistd.h>
00029 #include <stdio.h>
00030 
00031 // KDE
00032 #include <kde_file.h>
00033 #include <kdebug.h>
00034 
00035 using namespace Konsole;
00036 
00037 static int blocksize = 0;
00038 
00039 BlockArray::BlockArray()
00040     : size(0),
00041       current(size_t(-1)),
00042       index(size_t(-1)),
00043       lastmap(0),
00044       lastmap_index(size_t(-1)),
00045       lastblock(0), ion(-1),
00046       length(0)
00047 {
00048     // lastmap_index = index = current = size_t(-1);
00049     if (blocksize == 0)
00050         blocksize = ((sizeof(Block) / getpagesize()) + 1) * getpagesize();
00051 
00052 }
00053 
00054 BlockArray::~BlockArray()
00055 {
00056     setHistorySize(0);
00057     assert(!lastblock);
00058 }
00059 
00060 size_t BlockArray::append(Block *block)
00061 {
00062     if (!size)
00063         return size_t(-1);
00064 
00065     ++current;
00066     if (current >= size) current = 0;
00067 
00068     int rc;
00069     rc = KDE_lseek(ion, current * blocksize, SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setHistorySize(0); return size_t(-1); }
00070     rc = write(ion, block, blocksize); if (rc < 0) { perror("HistoryBuffer::add.write"); setHistorySize(0); return size_t(-1); }
00071 
00072     length++;
00073     if (length > size) length = size;
00074 
00075     ++index;
00076 
00077     delete block;
00078     return current;
00079 }
00080 
00081 size_t BlockArray::newBlock()
00082 {
00083     if (!size)
00084         return size_t(-1);
00085     append(lastblock);
00086 
00087     lastblock = new Block();
00088     return index + 1;
00089 }
00090 
00091 Block *BlockArray::lastBlock() const
00092 {
00093     return lastblock;
00094 }
00095 
00096 bool BlockArray::has(size_t i) const
00097 {
00098     if (i == index + 1)
00099         return true;
00100 
00101     if (i > index)
00102         return false;
00103     if (index - i >= length)
00104         return false;
00105     return true;
00106 }
00107 
00108 const Block* BlockArray::at(size_t i)
00109 {
00110     if (i == index + 1)
00111         return lastblock;
00112 
00113     if (i == lastmap_index)
00114         return lastmap;
00115 
00116     if (i > index) {
00117         kDebug(1211) << "BlockArray::at() i > index\n";
00118         return 0;
00119     }
00120     
00121 //     if (index - i >= length) {
00122 //         kDebug(1211) << "BlockArray::at() index - i >= length\n";
00123 //         return 0;
00124 //     }
00125 
00126     size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
00127 
00128     assert(j < size);
00129     unmap();
00130 
00131     Block *block = (Block*)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);
00132 
00133     if (block == (Block*)-1) { perror("mmap"); return 0; }
00134 
00135     lastmap = block;
00136     lastmap_index = i;
00137 
00138     return block;
00139 }
00140 
00141 void BlockArray::unmap()
00142 {
00143     if (lastmap) {
00144         int res = munmap((char*)lastmap, blocksize);
00145         if (res < 0) perror("munmap");
00146     }
00147     lastmap = 0;
00148     lastmap_index = size_t(-1);
00149 }
00150 
00151 bool BlockArray::setSize(size_t newsize)
00152 {
00153     return setHistorySize(newsize * 1024 / blocksize);
00154 }
00155 
00156 bool BlockArray::setHistorySize(size_t newsize)
00157 {
00158 //    kDebug(1211) << "setHistorySize " << size << " " << newsize;
00159 
00160     if (size == newsize)
00161         return false;
00162 
00163     unmap();
00164 
00165     if (!newsize) {
00166         delete lastblock;
00167         lastblock = 0;
00168         if (ion >= 0) close(ion);
00169         ion = -1;
00170         current = size_t(-1);
00171         return true;
00172     }
00173 
00174     if (!size) {
00175         FILE* tmp = tmpfile();
00176         if (!tmp) {
00177             perror("konsole: cannot open temp file.\n");
00178         } else {
00179             ion = dup(fileno(tmp));
00180             if (ion<0) {
00181                 perror("konsole: cannot dup temp file.\n");
00182                 fclose(tmp);
00183             }
00184         }
00185         if (ion < 0)
00186             return false;
00187 
00188         assert(!lastblock);
00189 
00190         lastblock = new Block();
00191         size = newsize;
00192         return false;
00193     }
00194 
00195     if (newsize > size) {
00196         increaseBuffer();
00197         size = newsize;
00198         return false;
00199     } else {
00200         decreaseBuffer(newsize);
00201         ftruncate(ion, length*blocksize);
00202         size = newsize;
00203 
00204         return true;
00205     }
00206 }
00207 
00208 void moveBlock(FILE *fion, int cursor, int newpos, char *buffer2)
00209 {
00210     int res = KDE_fseek(fion, cursor * blocksize, SEEK_SET);
00211     if (res)
00212         perror("fseek");
00213     res = fread(buffer2, blocksize, 1, fion);
00214     if (res != 1)
00215         perror("fread");
00216 
00217     res = KDE_fseek(fion, newpos * blocksize, SEEK_SET);
00218     if (res)
00219         perror("fseek");
00220     res = fwrite(buffer2, blocksize, 1, fion);
00221     if (res != 1)
00222         perror("fwrite");
00223     //    printf("moving block %d to %d\n", cursor, newpos);
00224 }
00225 
00226 void BlockArray::decreaseBuffer(size_t newsize)
00227 {
00228     if (index < newsize) // still fits in whole
00229         return;
00230 
00231     int offset = (current - (newsize - 1) + size) % size;
00232 
00233     if (!offset)
00234         return;
00235 
00236     // The Block constructor could do somthing in future...
00237     char *buffer1 = new char[blocksize];
00238 
00239     FILE *fion = fdopen(dup(ion), "w+b");
00240     if (!fion) {
00241         delete [] buffer1;
00242         perror("fdopen/dup");
00243         return;
00244     }
00245 
00246     int firstblock;
00247     if (current <= newsize) {
00248         firstblock = current + 1;
00249     } else {
00250         firstblock = 0;
00251     }
00252 
00253     size_t oldpos;
00254     for (size_t i = 0, cursor=firstblock; i < newsize; i++) {
00255         oldpos = (size + cursor + offset) % size;
00256         moveBlock(fion, oldpos, cursor, buffer1);
00257         if (oldpos < newsize) {
00258             cursor = oldpos;
00259         } else
00260             cursor++;
00261     }
00262 
00263     current = newsize - 1;
00264     length = newsize;
00265 
00266     delete [] buffer1;
00267 
00268     fclose(fion);
00269 
00270 }
00271 
00272 void BlockArray::increaseBuffer()
00273 {
00274     if (index < size) // not even wrapped once
00275         return;
00276 
00277     int offset = (current + size + 1) % size;
00278     if (!offset) // no moving needed
00279         return;
00280 
00281     // The Block constructor could do somthing in future...
00282     char *buffer1 = new char[blocksize];
00283     char *buffer2 = new char[blocksize];
00284 
00285     int runs = 1;
00286     int bpr = size; // blocks per run
00287 
00288     if (size % offset == 0) {
00289         bpr = size / offset;
00290         runs = offset;
00291     }
00292 
00293     FILE *fion = fdopen(dup(ion), "w+b");
00294     if (!fion) {
00295         perror("fdopen/dup");
00296     delete [] buffer1;
00297     delete [] buffer2;
00298         return;
00299     }
00300 
00301     int res;
00302     for (int i = 0; i < runs; i++)
00303     {
00304         // free one block in chain
00305         int firstblock = (offset + i) % size;
00306         res = KDE_fseek(fion, firstblock * blocksize, SEEK_SET);
00307         if (res)
00308             perror("fseek");
00309         res = fread(buffer1, blocksize, 1, fion);
00310         if (res != 1)
00311             perror("fread");
00312         int newpos = 0;
00313         for (int j = 1, cursor=firstblock; j < bpr; j++)
00314         {
00315             cursor = (cursor + offset) % size;
00316             newpos = (cursor - offset + size) % size;
00317             moveBlock(fion, cursor, newpos, buffer2);
00318         }
00319         res = KDE_fseek(fion, i * blocksize, SEEK_SET);
00320         if (res)
00321             perror("fseek");
00322         res = fwrite(buffer1, blocksize, 1, fion);
00323         if (res != 1)
00324             perror("fwrite");
00325     }
00326     current = size - 1;
00327     length = size;
00328 
00329     delete [] buffer1;
00330     delete [] buffer2;
00331 
00332     fclose(fion);
00333 
00334 }
00335 

Konsole

Skip menu "Konsole"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • Konsole
  • Libraries
  •   libkonq
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal