• Skip to content
  • Skip to link menu
KDE 4.1 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 <kdebug.h>
00033 
00034 using namespace Konsole;
00035 
00036 static int blocksize = 0;
00037 
00038 BlockArray::BlockArray()
00039     : size(0),
00040       current(size_t(-1)),
00041       index(size_t(-1)),
00042       lastmap(0),
00043       lastmap_index(size_t(-1)),
00044       lastblock(0), ion(-1),
00045       length(0)
00046 {
00047     // lastmap_index = index = current = size_t(-1);
00048     if (blocksize == 0)
00049         blocksize = ((sizeof(Block) / getpagesize()) + 1) * getpagesize();
00050 
00051 }
00052 
00053 BlockArray::~BlockArray()
00054 {
00055     setHistorySize(0);
00056     assert(!lastblock);
00057 }
00058 
00059 size_t BlockArray::append(Block *block)
00060 {
00061     if (!size)
00062         return size_t(-1);
00063 
00064     ++current;
00065     if (current >= size) current = 0;
00066 
00067     int rc;
00068     rc = lseek(ion, current * blocksize, SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setHistorySize(0); return size_t(-1); }
00069     rc = write(ion, block, blocksize); if (rc < 0) { perror("HistoryBuffer::add.write"); setHistorySize(0); return size_t(-1); }
00070 
00071     length++;
00072     if (length > size) length = size;
00073 
00074     ++index;
00075 
00076     delete block;
00077     return current;
00078 }
00079 
00080 size_t BlockArray::newBlock()
00081 {
00082     if (!size)
00083         return size_t(-1);
00084     append(lastblock);
00085 
00086     lastblock = new Block();
00087     return index + 1;
00088 }
00089 
00090 Block *BlockArray::lastBlock() const
00091 {
00092     return lastblock;
00093 }
00094 
00095 bool BlockArray::has(size_t i) const
00096 {
00097     if (i == index + 1)
00098         return true;
00099 
00100     if (i > index)
00101         return false;
00102     if (index - i >= length)
00103         return false;
00104     return true;
00105 }
00106 
00107 const Block* BlockArray::at(size_t i)
00108 {
00109     if (i == index + 1)
00110         return lastblock;
00111 
00112     if (i == lastmap_index)
00113         return lastmap;
00114 
00115     if (i > index) {
00116         kDebug(1211) << "BlockArray::at() i > index\n";
00117         return 0;
00118     }
00119     
00120 //     if (index - i >= length) {
00121 //         kDebug(1211) << "BlockArray::at() index - i >= length\n";
00122 //         return 0;
00123 //     }
00124 
00125     size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
00126 
00127     assert(j < size);
00128     unmap();
00129 
00130     Block *block = (Block*)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);
00131 
00132     if (block == (Block*)-1) { perror("mmap"); return 0; }
00133 
00134     lastmap = block;
00135     lastmap_index = i;
00136 
00137     return block;
00138 }
00139 
00140 void BlockArray::unmap()
00141 {
00142     if (lastmap) {
00143         int res = munmap((char*)lastmap, blocksize);
00144         if (res < 0) perror("munmap");
00145     }
00146     lastmap = 0;
00147     lastmap_index = size_t(-1);
00148 }
00149 
00150 bool BlockArray::setSize(size_t newsize)
00151 {
00152     return setHistorySize(newsize * 1024 / blocksize);
00153 }
00154 
00155 bool BlockArray::setHistorySize(size_t newsize)
00156 {
00157 //    kDebug(1211) << "setHistorySize " << size << " " << newsize;
00158 
00159     if (size == newsize)
00160         return false;
00161 
00162     unmap();
00163 
00164     if (!newsize) {
00165         delete lastblock;
00166         lastblock = 0;
00167         if (ion >= 0) close(ion);
00168         ion = -1;
00169         current = size_t(-1);
00170         return true;
00171     }
00172 
00173     if (!size) {
00174         FILE* tmp = tmpfile();
00175         if (!tmp) {
00176             perror("konsole: cannot open temp file.\n");
00177         } else {
00178             ion = dup(fileno(tmp));
00179             if (ion<0) {
00180                 perror("konsole: cannot dup temp file.\n");
00181                 fclose(tmp);
00182             }
00183         }
00184         if (ion < 0)
00185             return false;
00186 
00187         assert(!lastblock);
00188 
00189         lastblock = new Block();
00190         size = newsize;
00191         return false;
00192     }
00193 
00194     if (newsize > size) {
00195         increaseBuffer();
00196         size = newsize;
00197         return false;
00198     } else {
00199         decreaseBuffer(newsize);
00200         ftruncate(ion, length*blocksize);
00201         size = newsize;
00202 
00203         return true;
00204     }
00205 }
00206 
00207 void moveBlock(FILE *fion, int cursor, int newpos, char *buffer2)
00208 {
00209     int res = fseek(fion, cursor * blocksize, SEEK_SET);
00210     if (res)
00211         perror("fseek");
00212     res = fread(buffer2, blocksize, 1, fion);
00213     if (res != 1)
00214         perror("fread");
00215 
00216     res = fseek(fion, newpos * blocksize, SEEK_SET);
00217     if (res)
00218         perror("fseek");
00219     res = fwrite(buffer2, blocksize, 1, fion);
00220     if (res != 1)
00221         perror("fwrite");
00222     //    printf("moving block %d to %d\n", cursor, newpos);
00223 }
00224 
00225 void BlockArray::decreaseBuffer(size_t newsize)
00226 {
00227     if (index < newsize) // still fits in whole
00228         return;
00229 
00230     int offset = (current - (newsize - 1) + size) % size;
00231 
00232     if (!offset)
00233         return;
00234 
00235     // The Block constructor could do somthing in future...
00236     char *buffer1 = new char[blocksize];
00237 
00238     FILE *fion = fdopen(dup(ion), "w+b");
00239     if (!fion) {
00240         delete [] buffer1;
00241         perror("fdopen/dup");
00242         return;
00243     }
00244 
00245     int firstblock;
00246     if (current <= newsize) {
00247         firstblock = current + 1;
00248     } else {
00249         firstblock = 0;
00250     }
00251 
00252     size_t oldpos;
00253     for (size_t i = 0, cursor=firstblock; i < newsize; i++) {
00254         oldpos = (size + cursor + offset) % size;
00255         moveBlock(fion, oldpos, cursor, buffer1);
00256         if (oldpos < newsize) {
00257             cursor = oldpos;
00258         } else
00259             cursor++;
00260     }
00261 
00262     current = newsize - 1;
00263     length = newsize;
00264 
00265     delete [] buffer1;
00266 
00267     fclose(fion);
00268 
00269 }
00270 
00271 void BlockArray::increaseBuffer()
00272 {
00273     if (index < size) // not even wrapped once
00274         return;
00275 
00276     int offset = (current + size + 1) % size;
00277     if (!offset) // no moving needed
00278         return;
00279 
00280     // The Block constructor could do somthing in future...
00281     char *buffer1 = new char[blocksize];
00282     char *buffer2 = new char[blocksize];
00283 
00284     int runs = 1;
00285     int bpr = size; // blocks per run
00286 
00287     if (size % offset == 0) {
00288         bpr = size / offset;
00289         runs = offset;
00290     }
00291 
00292     FILE *fion = fdopen(dup(ion), "w+b");
00293     if (!fion) {
00294         perror("fdopen/dup");
00295     delete [] buffer1;
00296     delete [] buffer2;
00297         return;
00298     }
00299 
00300     int res;
00301     for (int i = 0; i < runs; i++)
00302     {
00303         // free one block in chain
00304         int firstblock = (offset + i) % size;
00305         res = fseek(fion, firstblock * blocksize, SEEK_SET);
00306         if (res)
00307             perror("fseek");
00308         res = fread(buffer1, blocksize, 1, fion);
00309         if (res != 1)
00310             perror("fread");
00311         int newpos = 0;
00312         for (int j = 1, cursor=firstblock; j < bpr; j++)
00313         {
00314             cursor = (cursor + offset) % size;
00315             newpos = (cursor - offset + size) % size;
00316             moveBlock(fion, cursor, newpos, buffer2);
00317         }
00318         res = fseek(fion, i * blocksize, SEEK_SET);
00319         if (res)
00320             perror("fseek");
00321         res = fwrite(buffer1, blocksize, 1, fion);
00322         if (res != 1)
00323             perror("fwrite");
00324     }
00325     current = size - 1;
00326     length = size;
00327 
00328     delete [] buffer1;
00329     delete [] buffer2;
00330 
00331     fclose(fion);
00332 
00333 }
00334 

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.4
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