├── .gitignore ├── AUTHORS ├── CMakeLists.txt ├── CMakeListsDeb.txt ├── ChangeLog ├── LICENSE ├── README.mkd ├── bin ├── array_test ├── clean.sh ├── get_test ├── stress_array_test ├── stress_value_test ├── unload.sh └── zero-cache.sh ├── conf ├── 70-zero-cache.rules ├── CMakeLists.txt ├── zero-cache.conf └── zero-cache.pc ├── debian ├── changelog ├── compat ├── control ├── postinst ├── rules ├── zero-cache-dev.install └── zero-cache.install ├── dkms.conf ├── source ├── CMakeLists.txt ├── client │ ├── CMakeLists.txt │ ├── typed_client.cpp │ ├── typed_client.h │ ├── untyped_client.cpp │ └── untyped_client.h ├── common │ ├── CMakeLists.txt │ ├── debug.cpp │ ├── debug.h │ ├── speaker.cpp │ ├── speaker.h │ ├── speed_test.h │ ├── thread.cpp │ ├── thread.h │ └── types_zcache.h └── server │ ├── Makefile │ ├── functions.c │ ├── zero_cache.c │ └── zero_cache.h └── test ├── CMakeLists.txt ├── array_test.cpp ├── get_test.cpp ├── stress_array_test.cpp └── stress_value_test.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Temporary files 2 | *.swp 3 | cscope.out 4 | *-journal 5 | *.log 6 | *~ 7 | *.o 8 | *.out 9 | *.ko 10 | *.o.cmd 11 | *.ko.cmd 12 | .tmp_versions/ 13 | Module.symvers 14 | modules.order 15 | *.mod.c 16 | 17 | # CMake temporary files 18 | *.cmake 19 | CMakeFiles 20 | CMakeCache.txt 21 | Makefile 22 | 23 | # Binaries 24 | *.so 25 | *.a 26 | stress_value_test 27 | stress_array_test 28 | get_test 29 | array_test 30 | 31 | # debian build files 32 | debian/*~ 33 | debian/buildroot/ 34 | debian/zero-cache-dev 35 | debian/zero-cache 36 | debian/*.debhelper.log 37 | debian/*.substvars 38 | install_manifest.txt 39 | *.1 40 | bin/deb/ 41 | build-stamp 42 | configure-stamp 43 | debian/files 44 | *.debhelper 45 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Alexander Gurov 2 | Ilya Shpigor 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Release build type: 2 | # cmake -D CMAKE_BUILD_TYPE=Release CMakeLists.txt 3 | # 4 | # Debug build type (by default): 5 | # cmake -D CMAKE_BUILD_TYPE=Debug CMakeLists.txt 6 | 7 | cmake_minimum_required(VERSION 2.6) 8 | project(zero-cache) 9 | 10 | set(COMMON_INCLUDE_DIRS 11 | ${PROJECT_SOURCE_DIR}/source/client 12 | ${PROJECT_SOURCE_DIR}/source/common 13 | ${PROJECT_SOURCE_DIR}/source/server) 14 | 15 | set(COMMON_LIBDIR 16 | ${PROJECT_SOURCE_DIR}/source/client 17 | ${PROJECT_SOURCE_DIR}/source/common 18 | ${PROJECT_SOURCE_DIR}/source/server) 19 | 20 | # Build type by default is Release 21 | if(NOT CMAKE_BUILD_TYPE) 22 | set(CMAKE_BUILD_TYPE Release) 23 | endif(NOT CMAKE_BUILD_TYPE) 24 | 25 | message(STATUS "Build type: " ${CMAKE_BUILD_TYPE}) 26 | 27 | # CXXFLAGS and CMAKE_C_FLAGS 28 | if(UNIX) 29 | set(CMAKE_CXX_FLAGS "-Wvla -Wl,-z,defs -fPIC") 30 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O2 -fomit-frame-pointer -funroll-loops -pipe") 31 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -g -O0 -D__DEBUG__") 32 | set(CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS_RELEASE}) 33 | endif(UNIX) 34 | 35 | # Subdirs 36 | add_subdirectory(source) 37 | add_subdirectory(test) 38 | add_subdirectory(conf) 39 | 40 | # Module 41 | add_custom_target(server ALL 42 | COMMAND make -f ${PROJECT_SOURCE_DIR}/source/server/Makefile 43 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/source/server) 44 | 45 | include(CMakeListsDeb.txt) 46 | -------------------------------------------------------------------------------- /CMakeListsDeb.txt: -------------------------------------------------------------------------------- 1 | set(BIN_DIR ${PROJECT_SOURCE_DIR}/bin) 2 | set(BIN_DEB_DIR ${BIN_DIR}/deb) 3 | set(DEBIAN_DIR ${PROJECT_SOURCE_DIR}/debian) 4 | set(MODULE_DIR ${PROJECT_SOURCE_DIR}/source/server) 5 | set(MODULE_NAME zero_cache) 6 | set(MODULE_VERSION 2.2) 7 | set(USR_SRC_DIR /usr/src/${MODULE_NAME}-${MODULE_VERSION}) 8 | 9 | # Targets for the deb packages building 10 | add_custom_target(deb-clean 11 | COMMAND -rm -rf build-stamp install_manifest.txt configure-stamp 12 | COMMAND find . -name "*.1" | xargs rm -f 13 | 14 | COMMAND -rm -rf ${DEBIAN_DIR}/buildroot 15 | COMMAND -rm -rf ${DEBIAN_DIR}/zero-cache 16 | COMMAND -rm -rf ${DEBIAN_DIR}/zero-cache-dev 17 | COMMAND find ${DEBIAN_DIR} -name "*.log" | xargs rm -f 18 | COMMAND find ${DEBIAN_DIR} -name "*.substvars" | xargs rm -f 19 | COMMAND find ${DEBIAN_DIR} -name "*.debhelper" | xargs rm -f 20 | 21 | COMMAND -rm -rf ${BIN_DEB_DIR} 22 | COMMAND find ${BIN_DIR} -name \"*.dsc\" | xargs rm -f 23 | COMMAND find ${BIN_DIR} -name "*.changes" | xargs rm -f 24 | COMMAND find ${BIN_DIR} -name "*.deb" | xargs rm -f 25 | COMMAND find ${BIN_DIR} -name "*.tar.gz" | xargs rm -f 26 | 27 | COMMAND -sudo dkms remove -m ${MODULE_NAME} -v ${MODULE_VERSION} --all 28 | COMMAND -sudo rm -Rf ${USR_SRC_DIR} 29 | ) 30 | 31 | add_custom_target(deb 32 | COMMAND mkdir -p ${BIN_DEB_DIR} 33 | COMMAND ${MKCHANGELOG} 34 | COMMAND dpkg-buildpackage -rfakeroot -b -us -uc 35 | COMMAND mv -f ../*.changes ../*.deb ${BIN_DEB_DIR} 36 | 37 | COMMAND -sudo mkdir ${USR_SRC_DIR} 38 | COMMAND -sudo cp -R ${MODULE_DIR}/* ${USR_SRC_DIR} 39 | COMMAND -sudo cp dkms.conf ${USR_SRC_DIR}/ 40 | COMMAND -sudo dkms add -m ${MODULE_NAME} -v ${MODULE_VERSION} 41 | COMMAND -sudo dkms build -m ${MODULE_NAME} -v ${MODULE_VERSION} 42 | COMMAND -sudo dkms mkdeb -m ${MODULE_NAME} -v ${MODULE_VERSION} 43 | COMMAND -cp -f /var/lib/dkms/${MODULE_NAME}/${MODULE_VERSION}/deb/* ${BIN_DEB_DIR} 44 | ) 45 | 46 | add_dependencies(deb deb-clean) 47 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | * zero-cache 2.2 2 | - Implement the cache cleaning mechanism 3 | - Build the server module in dkms 4 | 5 | * zero-cache 2.1 6 | - Add arrays and strings to supported caching data types 7 | - Add the untyped client class 8 | - Fix work with not real-time kernels 9 | 10 | * zero-cache 2.0 11 | - Implement caching system's server in the kernel module 12 | - Remove the type unsafe client class 13 | - Don't use ZMQ library for the client-server connection 14 | 15 | * zero-cache 1.6 16 | - Add limit for client's requests sending 17 | - Add timeout for server's requests waiting 18 | - Code refactoring 19 | 20 | * zero-cache 1.5 21 | - Fix bug with working through the TCP protocol 22 | - Change format of the key array answer 23 | 24 | * zero-cache 1.4 25 | - Add type safe client class with ClientWrap name 26 | - Add class to packaging readind and writing data 27 | 28 | * zero-cache 1.3 29 | - Implement receiving a list of all cached keys 30 | - Use const-correctness form for all classes 31 | - Refactoring of the project's code 32 | 33 | * zero-cache 1.2 34 | - Add function to get all available keys from cache 35 | - Disable all operation to write logs from Release build 36 | - Remove key values from the Reactor and Registrar answers 37 | 38 | * zero-cache 1.1 39 | - Don't use the CZMQ interface library 40 | - Fix the memory leaks 41 | 42 | * zero-cache 1.0 43 | - Fix working with the TCP sockets 44 | - Add CMake find modules 45 | 46 | * zero-cache 1.0 47 | - Fix working with the TCP sockets 48 | - Add CMake find modules 49 | 50 | * zero-cache 0.9 51 | - Accelerate the key registration procedure 52 | - Accelerate receiving data by clients 53 | - Use client identifiers mechanism instead the server ports assignment 54 | - Change the common library type to static 55 | - Fix bug with debian packaging 56 | 57 | * zero-cache 0.8 58 | - Support TCP sockets 59 | - Fix memory leak bugs 60 | - Add critical errors printing to stdout mechanism 61 | 62 | * zero-cache 0.7 63 | - Support both dealer and publisher-subscriber types of sockets 64 | - Fix bugs with read from cache operation 65 | 66 | * zero-cache 0.6 67 | - Implement bidirectional data transmission with publisher-subscriber pattern 68 | - Encapsulate socket operations in the Socket class 69 | - Fix bug with passing queue size for clients and reactors 70 | - Fix bug with application interruption on Ctrl-C pressing 71 | 72 | * zero-cache 0.5 73 | - Use one thread to process requests for several keys 74 | - Use one client to access data from several keys 75 | 76 | * zero-cache 0.4 77 | - Implement multithread server architecture 78 | - Fix debian packaging errors 79 | 80 | * zero-cache 0.3 81 | - Packaging application for debian 82 | 83 | * zero-cache 0.2 84 | - Fix bugs and memory leaks 85 | 86 | * zero-cache 0.1 87 | - Base functional implementation 88 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.mkd: -------------------------------------------------------------------------------- 1 | Zero Cache 2.2 version 2 | ====================== 3 | 4 | INTRODUCTION 5 | ------------ 6 | 7 | Zero Cache is a open source, high-performance, kernel space memory caching system. 8 | 9 | Zero Cache is able to store data of any type that are addressed by 10 | index numbers. It provides the minimal response time thanks to direct memory 11 | copying between the user space and kernel space. 12 | 13 | BUILDING 14 | -------- 15 | 16 | You need the CMake build system, C++ and C compilers to build this software. 17 | 18 | 1. Generate makefiles with CMake build system.
19 | Type one of these commands to build debug or release versions of the zero-cache: 20 | 21 | $ cmake -D CMAKE_BUILD_TYPE=Debug CMakeLists.txt 22 | 23 | $ cmake -D CMAKE_BUILD_TYPE=Release CMakeLists.txt 24 | 25 | 2. Build binaries with C++ and C compilers: 26 | 27 | $ make 28 | 29 | 3. Build debian package if you use Debian-based Linux distribution: 30 | 31 | $ make deb 32 | 33 | You can find debian packages in the `zero-cache/bin/deb` directory. 34 | 35 | INSTALLING 36 | ---------- 37 | 38 | Debian-based Linux distribution users can install debian packages from 39 | `zero-cache/bin/deb` directory. 40 | 41 | Another way is installing with Makefile default mechanism: 42 | 43 | $ make install 44 | 45 | USAGE 46 | ----- 47 | 48 | First of all you must load the server zero-cache module into your kernel: 49 | 50 | $ insmod source/server/zero_cache.ko 51 | 52 | The `zero_cache` device file will be created at the `/dev` directory. Now the 53 | zero-cache server is ready to work. 54 | 55 | You can interact with zero-cache server directly with `ioctl` function. Another 56 | way is usage `Client` interface class for your C++ applications. 57 | 58 | EXAMPLES 59 | -------- 60 | 61 | This is example of typical C++ client application: 62 | 63 | #include 64 | 65 | using namespace zero_cache; 66 | 67 | int main() 68 | { 69 | TypedClient client; 70 | 71 | size_t index = 0; 72 | long data = 1024; 73 | 74 | client.Writelong(index, data); 75 | 76 | long result = client.ReadLong(index); 77 | 78 | return 0; 79 | } 80 | 81 | This is example of typical C client application: 82 | 83 | #include 84 | 85 | int main() 86 | { 87 | int dev_file; 88 | 89 | dev_file = open(DEVICE_FILE_NAME, 0); 90 | 91 | long data; 92 | data = 1024; 93 | 94 | Package package; 95 | package.index = 0; 96 | memcpy(&package.data, data, PACKAGE_DATA_SIZE); 97 | 98 | ioctl(dev_file, IOCTL_WRITE_VALUE, &package); 99 | 100 | long result; 101 | 102 | package.index = 0; 103 | ioctl(dev_file, IOCTL_READ_VALUE, &package); 104 | memcpy(result, &package.data, PACKAGE_DATA_SIZE); 105 | 106 | close(dev_file); 107 | 108 | return 0; 109 | } 110 | 111 | COPYING 112 | ------- 113 | 114 | Free use of this software is granted under the terms of the GNU Lesser General 115 | Public License (LGPL). For details see the file `LICENSE` included with the zero-cache distribution. 116 | -------------------------------------------------------------------------------- /bin/array_test: -------------------------------------------------------------------------------- 1 | ../test/array_test -------------------------------------------------------------------------------- /bin/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -f *.log 4 | 5 | for (( i=0; i<=50; i++ )) 6 | do 7 | rm $i 8 | done 9 | 10 | rm -f /var/run/zero-cache/* 11 | -------------------------------------------------------------------------------- /bin/get_test: -------------------------------------------------------------------------------- 1 | ../test/get_test -------------------------------------------------------------------------------- /bin/stress_array_test: -------------------------------------------------------------------------------- 1 | ../test/stress_array_test -------------------------------------------------------------------------------- /bin/stress_value_test: -------------------------------------------------------------------------------- 1 | ../test/stress_value_test -------------------------------------------------------------------------------- /bin/unload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo rmmod zero_cache 4 | -------------------------------------------------------------------------------- /bin/zero-cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo rmmod zero_cache 4 | sudo rm -f /dev/zero_cache 5 | sudo insmod ../source/server/zero_cache.ko 6 | -------------------------------------------------------------------------------- /conf/70-zero-cache.rules: -------------------------------------------------------------------------------- 1 | KERNEL=="zero_cache", NAME="%k", MODE="0666" 2 | -------------------------------------------------------------------------------- /conf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install(FILES zero-cache.conf DESTINATION /etc/ld.so.conf.d) 2 | install(FILES zero-cache.pc DESTINATION /usr/lib/pkgconfig) 3 | install(FILES 70-zero-cache.rules DESTINATION /etc/udev/rules.d) 4 | -------------------------------------------------------------------------------- /conf/zero-cache.conf: -------------------------------------------------------------------------------- 1 | # path to shared library for ldconfig (copied at /etc/ld.so.conf.d) 2 | /usr/lib/zero-cache 3 | -------------------------------------------------------------------------------- /conf/zero-cache.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib/zero-cache 4 | includedir=${prefix}/include/zero-cache 5 | modules=1 6 | 7 | Name: zero-cache 8 | Version: 2.2 9 | Description: Kernel space memory caching system 10 | Requires: 11 | Libs: -L${libdir} -lzero_cache 12 | Libs.private: 13 | Cflags: -I${includedir} 14 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | zero-cache (2.2) precise; urgency=low 2 | 3 | * Implement the cache cleaning mechanism 4 | * Build the server module in dkms 5 | 6 | -- Ilya Shpigor Thu, 07 Mar 2013 12:39:05 +0400 7 | 8 | zero-cache (2.1) precise; urgency=low 9 | 10 | * Add arrays and strings to supported caching data types 11 | * Add the untyped client class 12 | * Fix work with not real-time kernels 13 | 14 | -- Ilya Shpigor Wed, 06 Mar 2013 17:30:15 +0400 15 | 16 | zero-cache (2.0) precise; urgency=low 17 | 18 | * Implement caching system's server in the kernel module 19 | * Remove the type unsafe client class 20 | * Don't use ZMQ library for the client-server connection 21 | 22 | -- Ilya Shpigor Sun, 03 Mar 2013 22:19:34 +0400 23 | 24 | zero-cache (1.6) precise; urgency=low 25 | 26 | * Add limit for client's requests sending 27 | * Add timeout for server's requests waiting 28 | * Code refactoring 29 | 30 | -- Ilya Shpigor Fri, 15 Feb 2013 09:50:07 +0400 31 | 32 | zero-cache (1.5) precise; urgency=low 33 | 34 | * Fix bug with working through the TCP protocol 35 | * Change format of the key array answer 36 | 37 | -- Ilya Shpigor Tue, 12 Feb 2013 15:05:04 +0400 38 | 39 | zero-cache (1.4) precise; urgency=low 40 | 41 | * Add type safe client class with ClientWrap name 42 | * Add class to packaging readind and writing data 43 | 44 | -- Ilya Shpigor Wed, 06 Feb 2013 13:52:14 +0400 45 | 46 | zero-cache (1.3) precise; urgency=low 47 | 48 | * Implement receiving a list of all cached keys 49 | * Use const-correctness form for all classes 50 | * Refactoring of the project's code 51 | 52 | -- Ilya Shpigor Tue, 1 Feb 2013 14:00:00 +0400 53 | 54 | zero-cache (1.2) precise; urgency=low 55 | 56 | * Add function to get all available keys from cache 57 | * Disable all operation to write logs from Release build 58 | * Remove key values from the Reactor and Registrar answers 59 | 60 | -- Ilya Shpigor Tue, 29 Jan 2013 15:06:04 +0400 61 | 62 | zero-cache (1.1) precise; urgency=low 63 | 64 | * Don't use the CZMQ interface library 65 | * Fix the memory leaks 66 | 67 | -- Ilya Shpigor Fri, 18 Jan 2013 15:47:46 +0400 68 | 69 | zero-cache (1.0) precise; urgency=low 70 | 71 | * Fix working with the TCP sockets 72 | * Add CMake find modules 73 | 74 | -- Ilya Shpigor Thu, 03 Jan 2013 13:24:18 +0400 75 | 76 | zero-cache (0.9) precise; urgency=low 77 | 78 | * Accelerate the key registration procedure 79 | * Accelerate receiving data by clients 80 | * Use client identifiers mechanism instead the server ports assignment 81 | * Change the common library type to static 82 | * Fix bug with debian packaging 83 | 84 | -- Ilya Shpigor Thu, 27 Dec 2012 11:35:43 +0400 85 | 86 | zero-cache (0.8) precise; urgency=low 87 | 88 | * Support TCP sockets 89 | * Fix memory leak bugs 90 | * Add critical errors printing to stdout mechanism 91 | 92 | -- Ilya Shpigor Wed, 19 Dec 2012 11:45:25 +0400 93 | 94 | zero-cache (0.7) precise; urgency=low 95 | 96 | * Support both dealer and publisher-subscriber types of sockets 97 | * Fix bugs with read from cache operation 98 | 99 | -- Ilya Shpigor Thu, 13 Dec 2012 16:54:46 +0400 100 | 101 | zero-cache (0.6) precise; urgency=low 102 | 103 | * Implement bidirectional data transmission with publisher-subscriber pattern 104 | * Encapsulate socket operations in the Socket class 105 | * Fix bug with passing queue size for clients and reactors 106 | * Fix bug with application interruption on Ctrl-C pressing 107 | 108 | -- Ilya Shpigor Wed, 12 Dec 2012 17:27:28 +0400 109 | 110 | zero-cache (0.5) precise; urgency=low 111 | 112 | * Use one thread to process requests for several keys 113 | * Use one client to access data from several keys 114 | 115 | -- Ilya Shpigor Fri, 07 Dec 2012 17:13:47 +0400 116 | 117 | zero-cache (0.4) precise; urgency=low 118 | 119 | * Implement multithread server architecture 120 | * Fix debian packaging errors 121 | 122 | -- Ilya Shpigor Fri, 07 Dec 2012 14:13:36 +0400 123 | 124 | zero-cache (0.3) stable; urgency=low 125 | 126 | * First package version 127 | 128 | -- Ilya Shpigor Tue, 04 Dec 2012 16:37:33 +0400 129 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: zero-cache 2 | Section: main 3 | Priority: extra 4 | Maintainer: Ilya Shpigor 5 | Build-Depends: debhelper (>= 5) 6 | Standards-Version: 3.7.2 7 | 8 | Package: zero-cache 9 | Architecture: any 10 | Depends: ${shlibs:Depends}, ${misc:Depends}, pkg-config 11 | Description: Kernel space memory caching system 12 | 13 | Package: zero-cache-dev 14 | Architecture: any 15 | Depends: ${shlibs:Depends}, ${misc:Depends} 16 | Description: Development files for zero-cache caching system 17 | -------------------------------------------------------------------------------- /debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postinst script for zero-cache 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `configure' 10 | # * `abort-upgrade' 11 | # * `abort-remove' `in-favour' 12 | # 13 | # * `abort-remove' 14 | # * `abort-deconfigure' `in-favour' 15 | # `removing' 16 | # 17 | # for details, see http://www.debian.org/doc/debian-policy/ or 18 | # the debian-policy package 19 | 20 | 21 | case "$1" in 22 | configure) 23 | ldconfig 24 | depmod -a 25 | ;; 26 | 27 | abort-upgrade|abort-remove|abort-deconfigure) 28 | ;; 29 | 30 | *) 31 | echo "postinst called with unknown argument \`$1'" >&2 32 | exit 1 33 | ;; 34 | esac 35 | 36 | # dh_installdeb will replace this with shell code automatically 37 | # generated by other debhelper scripts. 38 | 39 | #DEBHELPER# 40 | 41 | exit 0 42 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | #export DH_VERBOSE=1 11 | 12 | MAKE=make -f Makefile 13 | 14 | 15 | configure: configure-stamp 16 | configure-stamp: 17 | dh_testdir 18 | # Add here commands to configure the package. 19 | 20 | touch configure-stamp 21 | 22 | 23 | build: build-stamp 24 | 25 | build-stamp: configure-stamp 26 | dh_testdir 27 | 28 | # Add here commands to compile the package. 29 | $(MAKE) 30 | docbook-to-man debian/manpage.sgml > zero-cache.1 31 | 32 | touch $@ 33 | 34 | clean: 35 | dh_testdir 36 | dh_testroot 37 | rm -f build-stamp configure-stamp 38 | 39 | # Add here commands to clean up after the build process. 40 | #-$(MAKE) clean 41 | 42 | dh_clean -Xdeps 43 | 44 | install: build 45 | dh_testdir 46 | dh_testroot 47 | dh_clean -k -Xdeps 48 | dh_installdirs 49 | 50 | # Add here commands to install the package into debian/buildroot. 51 | $(MAKE) DESTDIR=$(CURDIR)/debian/buildroot install 52 | 53 | 54 | # Build architecture-independent files here. 55 | binary-indep: build install 56 | # We have nothing to do by default. 57 | 58 | # Build architecture-dependent files here. 59 | binary-arch: build install 60 | dh_testdir 61 | dh_testroot 62 | dh_installchangelogs 63 | dh_installdocs 64 | dh_installexamples 65 | 66 | dh_installdirs 67 | dh_installdocs 68 | dh_installexamples 69 | dh_install 70 | dh_installmenu 71 | dh_installman 72 | dh_installinit 73 | 74 | dh_installman 75 | dh_link 76 | dh_compress 77 | dh_fixperms 78 | dh_installdeb 79 | dh_shlibdeps 80 | dh_gencontrol 81 | dh_md5sums 82 | dh_builddeb 83 | 84 | binary: binary-indep binary-arch 85 | .PHONY: build clean binary-indep binary-arch binary install configure 86 | -------------------------------------------------------------------------------- /debian/zero-cache-dev.install: -------------------------------------------------------------------------------- 1 | debian/buildroot/usr/include/zero-cache/*.h usr/include/zero-cache 2 | debian/buildroot/usr/lib/pkgconfig/*.pc usr/lib/pkgconfig 3 | -------------------------------------------------------------------------------- /debian/zero-cache.install: -------------------------------------------------------------------------------- 1 | debian/buildroot/lib/modules lib 2 | debian/buildroot/usr/lib/zero-cache/libzero_cache.so usr/lib/zero-cache 3 | debian/buildroot/etc/ld.so.conf.d/*.conf etc/ld.so.conf.d 4 | debian/buildroot/etc/udev/rules.d/*.rules etc/udev/rules.d 5 | -------------------------------------------------------------------------------- /dkms.conf: -------------------------------------------------------------------------------- 1 | PACKAGE_NAME="zero_cache" 2 | PACKAGE_VERSION="2.2" 3 | MAKE[0]="make" 4 | 5 | BUILT_MODULE_NAME[0]="zero_cache" 6 | BUILT_MODULE_LOCATION[0]="." 7 | DEST_MODULE_LOCATION[0]="/kernel/lib" 8 | -------------------------------------------------------------------------------- /source/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | exec_program("uname -r" OUTPUT_VARIABLE UNAME) 2 | 3 | install(FILES server/zero_cache.ko DESTINATION /lib/modules/${UNAME}/kernel/lib) 4 | install(FILES server/zero_cache.h DESTINATION /usr/include/${PROJECT_NAME}) 5 | 6 | add_subdirectory(client) 7 | add_subdirectory(common) 8 | -------------------------------------------------------------------------------- /source/client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${COMMON_INCLUDE_DIRS}) 2 | link_directories(${COMMON_LIBDIR}) 3 | 4 | set(zero_cache_LIB_SRCS 5 | typed_client.cpp 6 | untyped_client.cpp) 7 | 8 | add_library(zero_cache SHARED ${zero_cache_LIB_SRCS}) 9 | 10 | if(UNIX) 11 | target_link_libraries(zero_cache common) 12 | endif(UNIX) 13 | 14 | install(TARGETS zero_cache DESTINATION /usr/lib/${PROJECT_NAME}) 15 | 16 | install(FILES 17 | typed_client.h 18 | untyped_client.h 19 | DESTINATION /usr/include/${PROJECT_NAME}) 20 | -------------------------------------------------------------------------------- /source/client/typed_client.cpp: -------------------------------------------------------------------------------- 1 | #include "typed_client.h" 2 | 3 | using namespace std; 4 | using namespace zero_cache; 5 | 6 | TypedClient::TypedClient(const char* log_file) : client_(log_file) 7 | { 8 | } 9 | 10 | void TypedClient::WriteLong(const size_t index, const long value) 11 | { 12 | client_.WriteValue(index, &value, sizeof(value)); 13 | } 14 | 15 | void TypedClient::WriteDouble(const size_t index, const double value) 16 | { 17 | client_.WriteValue(index, &value, sizeof(value)); 18 | } 19 | 20 | long TypedClient::ReadLong(const size_t index) const 21 | { 22 | long result; 23 | client_.ReadValue(index, &result, sizeof(result)); 24 | 25 | return result; 26 | } 27 | 28 | double TypedClient::ReadDouble(const size_t index) const 29 | { 30 | double result; 31 | client_.ReadValue(index, &result, sizeof(result)); 32 | 33 | return result; 34 | } 35 | 36 | void TypedClient::ClearCache() 37 | { 38 | client_.ClearCache(); 39 | } 40 | -------------------------------------------------------------------------------- /source/client/typed_client.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPED_CLIENT_H 2 | #define TYPED_CLIENT_H 3 | 4 | #include 5 | 6 | namespace zero_cache 7 | { 8 | 9 | class TypedClient 10 | { 11 | public: 12 | TypedClient(const char* log_file = ""); 13 | 14 | void WriteLong(const size_t index, const long value); 15 | void WriteDouble(const size_t index, const double value); 16 | 17 | long ReadLong(const size_t index) const; 18 | double ReadDouble(const size_t index) const; 19 | 20 | void ClearCache(); 21 | 22 | private: 23 | UntypedClient client_; 24 | }; 25 | 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /source/client/untyped_client.cpp: -------------------------------------------------------------------------------- 1 | #include "untyped_client.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define PRINTF Log 8 | #include "speed_test.h" 9 | #include "speaker.h" 10 | 11 | #include "zero_cache.h" 12 | 13 | using namespace std; 14 | using namespace zero_cache; 15 | 16 | UntypedClient::UntypedClient(const char* log_file) : Debug(log_file) 17 | { 18 | dev_file_ = open(DEVICE_FILE_NAME, 0); 19 | 20 | if ( dev_file_ < 0 ) 21 | Speaker::Instance()->PrintError(kOpenDevFileError); 22 | } 23 | 24 | UntypedClient::~UntypedClient() 25 | { 26 | close(dev_file_); 27 | } 28 | 29 | void UntypedClient::WriteValue(const size_t index, const void* value, const size_t size) 30 | { 31 | PRE_TIME_MEASURE("UntypedClient::WriteValue() ") 32 | 33 | Package package; 34 | package.index = index; 35 | package.size = size; 36 | memcpy(&package.data, value, POINTER_SIZE); 37 | 38 | int rc = ioctl(dev_file_, IOCTL_WRITE_VALUE, &package); 39 | 40 | if ( rc != 0 ) 41 | Speaker::Instance()->PrintError(kWriteError); 42 | 43 | POST_TIME_MEASURE 44 | } 45 | 46 | void UntypedClient::ReadValue(const size_t index, void* result, const size_t size) const 47 | { 48 | PRE_TIME_MEASURE("UntypedClient::ReadValue() ") 49 | 50 | Package package; 51 | package.index = index; 52 | package.size = size; 53 | 54 | int rc = ioctl(dev_file_, IOCTL_READ_VALUE, &package); 55 | 56 | if ( rc != 0 ) 57 | Speaker::Instance()->PrintError(kReadError); 58 | 59 | memcpy(result, &package.data, size); 60 | 61 | POST_TIME_MEASURE 62 | } 63 | 64 | void UntypedClient::WriteArray(const size_t index, const void* array, const size_t size) 65 | { 66 | PRE_TIME_MEASURE("UntypedClient::WriteArray() ") 67 | 68 | Package package; 69 | package.index = index; 70 | package.size = size; 71 | 72 | unsigned long address = reinterpret_cast(array); 73 | memcpy(&package.data, &address, POINTER_SIZE); 74 | 75 | int rc = ioctl(dev_file_, IOCTL_WRITE_ARRAY, &package); 76 | 77 | if ( rc != 0 ) 78 | Speaker::Instance()->PrintError(kWriteError); 79 | 80 | POST_TIME_MEASURE 81 | } 82 | 83 | void UntypedClient::ReadArray(const size_t index, void* result, const size_t size) const 84 | { 85 | /* FIXME: This function is the same as WriteArray() */ 86 | PRE_TIME_MEASURE("UntypedClient::ReadArray() ") 87 | 88 | Package package; 89 | package.index = index; 90 | package.size = size; 91 | 92 | unsigned long address = reinterpret_cast(result); 93 | memcpy(&package.data, &address, POINTER_SIZE); 94 | 95 | int rc = ioctl(dev_file_, IOCTL_READ_ARRAY, &package); 96 | 97 | if ( rc != 0 ) 98 | Speaker::Instance()->PrintError(kReadError); 99 | 100 | POST_TIME_MEASURE 101 | } 102 | 103 | void UntypedClient::ClearCache() 104 | { 105 | PRE_TIME_MEASURE("UntypedClient::ClearCache() ") 106 | 107 | Package package; 108 | package.index = 0; 109 | 110 | int rc = ioctl(dev_file_, IOCTL_CLEAR_CACHE, &package); 111 | 112 | if ( rc != 0 ) 113 | Speaker::Instance()->PrintError(kClearError); 114 | 115 | POST_TIME_MEASURE 116 | } 117 | -------------------------------------------------------------------------------- /source/client/untyped_client.h: -------------------------------------------------------------------------------- 1 | #ifndef UNTYPED_CLIENT_H 2 | #define UNTYPED_CLIENT_H 3 | 4 | #include 5 | #include 6 | 7 | namespace zero_cache 8 | { 9 | 10 | class UntypedClient : protected Debug 11 | { 12 | public: 13 | UntypedClient(const char* log_file = ""); 14 | virtual ~UntypedClient(); 15 | 16 | void WriteValue(const size_t index, const void* value, const size_t size); 17 | void ReadValue(const size_t index, void* result, const size_t size) const; 18 | 19 | void WriteArray(const size_t index, const void* array, const size_t size); 20 | void ReadArray(const size_t index, void* result, const size_t size) const; 21 | 22 | void ClearCache(); 23 | 24 | private: 25 | int dev_file_; 26 | 27 | DISALLOW_COPY_AND_ASSIGN(UntypedClient) 28 | }; 29 | 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /source/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${COMMON_INCLUDE_DIRS}) 2 | link_directories(${COMMON_LIBDIR}) 3 | 4 | set(common_LIB_SRCS 5 | debug.cpp 6 | speaker.cpp 7 | thread.cpp) 8 | 9 | add_library(common STATIC ${common_LIB_SRCS}) 10 | 11 | if(UNIX) 12 | target_link_libraries(common pthread) 13 | endif(UNIX) 14 | 15 | install(FILES 16 | debug.h 17 | types_zcache.h 18 | DESTINATION /usr/include/${PROJECT_NAME}) 19 | -------------------------------------------------------------------------------- /source/common/debug.cpp: -------------------------------------------------------------------------------- 1 | #include "debug.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | using namespace zero_cache; 11 | 12 | static const char* kDefaultLogfile = "/dev/null"; 13 | 14 | Debug::Debug(const char* log_file) 15 | { 16 | #ifdef __DEBUG__ 17 | if ( strlen(log_file) != 0 ) 18 | file_.open(log_file, ios::out | ios::app); 19 | else 20 | file_.open(kDefaultLogfile, ios::out | ios::app); 21 | #endif 22 | } 23 | 24 | Debug::~Debug() 25 | { 26 | #ifdef __DEBUG__ 27 | file_.close(); 28 | #endif 29 | } 30 | 31 | void Debug::Log(const char* fmt, ...) const 32 | { 33 | #ifdef __DEBUG__ 34 | char buf[4096]; 35 | va_list arg_list; 36 | va_start(arg_list, fmt); 37 | vsprintf(buf, fmt, arg_list); 38 | 39 | file_ << buf; 40 | va_end(arg_list); 41 | #endif 42 | } 43 | 44 | void Debug::PrintMsg(void* msg) const 45 | { 46 | #ifdef __DEBUG__ 47 | char* data_hex = static_cast(msg); 48 | file_ << " data = " << data_hex << endl; 49 | #endif 50 | } 51 | -------------------------------------------------------------------------------- /source/common/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H 2 | #define DEBUG_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace zero_cache 9 | { 10 | 11 | class Debug 12 | { 13 | public: 14 | Debug(const char* log_file = ""); 15 | virtual ~Debug(); 16 | 17 | void Log(const char* fmt, ...) const; 18 | void PrintMsg(void* msg) const; 19 | 20 | private: 21 | mutable std::ofstream file_; 22 | 23 | DISALLOW_COPY_AND_ASSIGN(Debug); 24 | }; 25 | 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /source/common/speaker.cpp: -------------------------------------------------------------------------------- 1 | #include "speaker.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | using namespace std; 8 | using namespace zero_cache; 9 | 10 | Speaker* Speaker::instance_ = NULL; 11 | 12 | Speaker* Speaker::Instance() 13 | { 14 | if (instance_ == NULL) 15 | instance_ = new Speaker(); 16 | 17 | return instance_; 18 | } 19 | 20 | void Speaker::PrintError(const ErrorType error) const 21 | { 22 | if ( error == kOpenDevFileError ) 23 | cout << "error: can't OPEN device file" << endl; 24 | else if ( error == kWriteError ) 25 | cout << "error: ioctl with WRITE command failed" << endl; 26 | else if ( error == kReadError ) 27 | cout << "error: ioctl with READ command failed" << endl; 28 | else if ( error == kClearError ) 29 | cout << "error: ioctl with CLEAR command failed" << endl; 30 | 31 | exit(1); 32 | } 33 | -------------------------------------------------------------------------------- /source/common/speaker.h: -------------------------------------------------------------------------------- 1 | #ifndef SPEAKER_H 2 | #define SPEAKER_H 3 | 4 | namespace zero_cache 5 | { 6 | 7 | enum ErrorType 8 | { 9 | kOpenDevFileError = 0, 10 | kWriteError, 11 | kReadError, 12 | kClearError 13 | }; 14 | 15 | class Speaker 16 | { 17 | public: 18 | static Speaker* Instance(); 19 | 20 | void PrintError(const ErrorType error) const; 21 | 22 | private: 23 | static Speaker* instance_; 24 | 25 | Speaker() {}; 26 | }; 27 | 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /source/common/speed_test.h: -------------------------------------------------------------------------------- 1 | #ifndef SPEED_TEST_H 2 | #define SPEED_TEST_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #ifndef PRINTF 11 | #define PRINTF printf 12 | #endif 13 | 14 | #define PRE_TIME_MEASURE(function) \ 15 | PRINTF(function); \ 16 | struct timeval start, end; \ 17 | long mtime, seconds, useconds; \ 18 | gettimeofday(&start, NULL); 19 | 20 | #define POST_TIME_MEASURE \ 21 | gettimeofday(&end, NULL); \ 22 | seconds = end.tv_sec - start.tv_sec; \ 23 | useconds = end.tv_usec - start.tv_usec; \ 24 | mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; \ 25 | PRINTF(" - %lu milliseconds\n", mtime); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /source/common/thread.cpp: -------------------------------------------------------------------------------- 1 | #include "thread.h" 2 | 3 | #include 4 | 5 | using namespace zero_cache; 6 | 7 | void zero_cache::CreateThread(thread_fn* func, void* data) 8 | { 9 | pthread_t thread; 10 | 11 | pthread_create(&thread, NULL, func, data); 12 | } 13 | -------------------------------------------------------------------------------- /source/common/thread.h: -------------------------------------------------------------------------------- 1 | #ifndef THREAD_H 2 | #define THREAD_H 3 | 4 | namespace zero_cache 5 | { 6 | 7 | typedef void* (thread_fn) (void *data); 8 | 9 | void CreateThread(thread_fn* function, void* data); 10 | 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /source/common/types_zcache.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_ZCACHE_H 2 | #define TYPES_ZCACHE_H 3 | 4 | namespace zero_cache 5 | { 6 | 7 | /* A macro to disallow the copy constructor and operator= functions. 8 | * This should be used in the private: declarations for a class. */ 9 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 10 | private: \ 11 | TypeName(const TypeName&); \ 12 | TypeName& operator=(const TypeName&); 13 | 14 | /* Macros for binary functor for STL container definition */ 15 | #define BINARY_FUNCTOR(Name, type1, name1, type2, name2) \ 16 | struct Name : public binary_function \ 17 | { \ 18 | void operator()(type1 name1, type2 name2) const \ 19 | { 20 | 21 | #define END_BINARY_FUNCTOR \ 22 | } \ 23 | }; 24 | 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /source/server/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += zero_cache.o 2 | 3 | KVER := `uname -r` 4 | KDIR ?= /lib/modules/$(KVER)/build 5 | 6 | all: 7 | $(MAKE) -C $(KDIR) M=$(PWD) modules 8 | 9 | clean: 10 | $(MAKE) -C $(KDIR) M=$(PWD) clean 11 | -------------------------------------------------------------------------------- /source/server/functions.c: -------------------------------------------------------------------------------- 1 | #define TRUE 1 2 | #define FALSE 0 3 | 4 | void set_pool_index(const size_t cache_index, const size_t size) 5 | { 6 | memcpy(&gCache[cache_index], &gIndexPool, sizeof(gIndexPool)); 7 | gIndexPool = gIndexPool + size; 8 | } 9 | 10 | size_t get_pool_index(const size_t cache_index) 11 | { 12 | size_t result; 13 | memcpy(&result, &gCache[cache_index], sizeof(result)); 14 | 15 | return result; 16 | } 17 | 18 | int is_pool_limit(const size_t index, const size_t size) 19 | { 20 | if ( CACHE_SIZE < (index + size) ) 21 | { 22 | printk(KERN_INFO "zero_cache: limit of the memory pool have been reached"); 23 | return TRUE; 24 | } 25 | else 26 | return FALSE; 27 | } 28 | 29 | void* data_to_pointer(const unsigned char const * data) 30 | { 31 | void* result; 32 | result = (void*)(*(unsigned long*)data); 33 | 34 | return result; 35 | } 36 | 37 | int is_data_empty(const size_t index) 38 | { 39 | unsigned long data; 40 | 41 | memcpy(&data, gCache[index], sizeof(data)); 42 | 43 | if ( data == 0 ) 44 | return TRUE; 45 | else 46 | return FALSE; 47 | } 48 | 49 | void clear_cache(void) 50 | { 51 | memset(&gCache, 0x00, sizeof(gCache)); 52 | memset(&gPool, 0x00, sizeof(gPool)); 53 | gIndexPool = 0; 54 | } 55 | -------------------------------------------------------------------------------- /source/server/zero_cache.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "zero_cache.h" 10 | 11 | MODULE_LICENSE("GPL"); 12 | MODULE_AUTHOR("Ilya Shpigor "); 13 | MODULE_DESCRIPTION("Kernel data cache module"); 14 | 15 | #define CLASS "zero_cache_class" 16 | #define DEVICE "zero_cache" 17 | #define CACHE_SIZE 100000 18 | 19 | static struct Device 20 | { 21 | dev_t number; 22 | struct cdev chrdev; 23 | struct class* class; 24 | } gDevice; 25 | 26 | DECLARE_RWSEM(gSem); 27 | 28 | static unsigned char gCache[CACHE_SIZE][POINTER_SIZE]; 29 | static unsigned char gPool[CACHE_SIZE]; 30 | static size_t gIndexPool = 0; 31 | 32 | #include "functions.c" 33 | 34 | static long zc_ioctl(struct file *file, unsigned int command, unsigned long arg) 35 | { 36 | struct Package* package; 37 | package = (struct Package*)arg; 38 | 39 | if ( (package->index) < 0 || (CACHE_SIZE < package->index) ) 40 | { 41 | printk(KERN_INFO "zero_cache: array index %lu out of bounds %d\n", package->index, CACHE_SIZE); 42 | return -1; 43 | } 44 | 45 | switch (command) 46 | { 47 | case IOCTL_WRITE_VALUE: 48 | down_write(&gSem); 49 | copy_from_user(&gCache[package->index], &package->data, POINTER_SIZE); 50 | up_write(&gSem); 51 | break; 52 | 53 | case IOCTL_READ_VALUE: 54 | down_read(&gSem); 55 | copy_to_user(&package->data, &gCache[package->index], POINTER_SIZE); 56 | up_read(&gSem); 57 | break; 58 | 59 | case IOCTL_WRITE_ARRAY: 60 | down_write(&gSem); 61 | if ( is_pool_limit(gIndexPool, package->size) ) 62 | { 63 | up_write(&gSem); 64 | return -1; 65 | } 66 | 67 | if ( is_data_empty(package->index) ) 68 | set_pool_index(package->index, package->size); 69 | 70 | copy_from_user(&gPool[get_pool_index(package->index)], 71 | data_to_pointer(&package->data[0]), package->size); 72 | up_write(&gSem); 73 | break; 74 | 75 | case IOCTL_READ_ARRAY: 76 | if ( is_pool_limit(get_pool_index(package->index), package->size) ) 77 | return -1; 78 | 79 | down_read(&gSem); 80 | copy_to_user(data_to_pointer(&package->data[0]), 81 | &gPool[get_pool_index(package->index)], package->size); 82 | up_read(&gSem); 83 | break; 84 | 85 | case IOCTL_CLEAR_CACHE: 86 | down_write(&gSem); 87 | clear_cache(); 88 | up_write(&gSem); 89 | break; 90 | } 91 | 92 | return 0; 93 | } 94 | 95 | int register_device(struct file_operations* fops) 96 | { 97 | if ( alloc_chrdev_region(&gDevice.number, 0, 1, DEVICE ) < 0 ) 98 | return -1; 99 | 100 | gDevice.class = class_create(THIS_MODULE, CLASS); 101 | if ( gDevice.class == NULL ) 102 | { 103 | unregister_chrdev_region(gDevice.number, 1); 104 | return -1; 105 | } 106 | 107 | if ( device_create(gDevice.class, NULL, gDevice.number, NULL, DEVICE) == NULL ) 108 | { 109 | class_destroy(gDevice.class); 110 | unregister_chrdev_region(gDevice.number, 1); 111 | return -1; 112 | } 113 | 114 | cdev_init(&gDevice.chrdev, fops); 115 | if ( cdev_add(&gDevice.chrdev, gDevice.number, 1) == -1 ) 116 | { 117 | device_destroy(gDevice.class, gDevice.number); 118 | class_destroy(gDevice.class); 119 | unregister_chrdev_region(gDevice.number, 1); 120 | return -1; 121 | } 122 | return 0; 123 | } 124 | 125 | static struct file_operations zc_fops = 126 | { 127 | .owner = THIS_MODULE, 128 | .unlocked_ioctl = zc_ioctl 129 | }; 130 | 131 | static int __init zc_init(void) 132 | { 133 | int rc; 134 | rc = register_device(&zc_fops); 135 | 136 | clear_cache(); 137 | 138 | printk(KERN_INFO "zero_cache: init rc=%d\n", rc); 139 | return rc; 140 | } 141 | 142 | static void __exit zc_exit(void) 143 | { 144 | cdev_del(&gDevice.chrdev); 145 | device_destroy(gDevice.class, gDevice.number); 146 | class_destroy(gDevice.class); 147 | unregister_chrdev_region(gDevice.number, 1); 148 | 149 | printk(KERN_INFO "zero_cache: exit\n"); 150 | } 151 | 152 | module_init(zc_init); 153 | module_exit(zc_exit); 154 | 155 | -------------------------------------------------------------------------------- /source/server/zero_cache.h: -------------------------------------------------------------------------------- 1 | #ifndef ZERO_CACHE_H 2 | #define ZERO_CACHE_H 3 | 4 | #include 5 | 6 | #define MAJOR_NUM 100 7 | 8 | #define IOCTL_WRITE_VALUE _IOW(MAJOR_NUM, 0, void *) 9 | #define IOCTL_READ_VALUE _IOR(MAJOR_NUM, 1, void *) 10 | #define IOCTL_WRITE_ARRAY _IOW(MAJOR_NUM, 2, void *) 11 | #define IOCTL_READ_ARRAY _IOR(MAJOR_NUM, 3, void *) 12 | #define IOCTL_CLEAR_CACHE _IOR(MAJOR_NUM, 4, void *) 13 | 14 | #define DEVICE_FILE_NAME "/dev/zero_cache" 15 | 16 | /* FIXME: Use the universal way to calculate pointer size */ 17 | #define POINTER_SIZE 8 18 | 19 | struct Package 20 | { 21 | size_t index; 22 | size_t size; 23 | unsigned char data[POINTER_SIZE]; 24 | }; 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${COMMON_INCLUDE_DIRS}) 2 | link_directories(${COMMON_LIBDIR}) 3 | 4 | 5 | set(get_test_SRCS 6 | get_test.cpp) 7 | 8 | add_executable(get_test ${get_test_SRCS}) 9 | 10 | target_link_libraries(get_test zero_cache) 11 | 12 | install(TARGETS get_test DESTINATION bin) 13 | 14 | 15 | set(stress_value_test_SRCS 16 | stress_value_test.cpp) 17 | 18 | add_executable(stress_value_test ${stress_value_test_SRCS}) 19 | 20 | target_link_libraries(stress_value_test zero_cache) 21 | 22 | install(TARGETS stress_value_test DESTINATION bin) 23 | 24 | 25 | set(array_test_SRCS 26 | array_test.cpp) 27 | 28 | add_executable(array_test ${array_test_SRCS}) 29 | 30 | target_link_libraries(array_test zero_cache) 31 | 32 | install(TARGETS array_test DESTINATION bin) 33 | 34 | 35 | set(stress_array_test_SRCS 36 | stress_array_test.cpp) 37 | 38 | add_executable(stress_array_test ${stress_array_test_SRCS}) 39 | 40 | target_link_libraries(stress_array_test zero_cache) 41 | 42 | install(TARGETS stress_array_test DESTINATION bin) 43 | -------------------------------------------------------------------------------- /test/array_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "untyped_client.h" 7 | 8 | using namespace std; 9 | using namespace zero_cache; 10 | 11 | static const size_t kIndex1 = 0; 12 | static const string kData1 = "test data 1"; 13 | 14 | static const size_t kIndex2 = 1; 15 | static const unsigned char kData2[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 16 | 17 | void InitData(UntypedClient& client) 18 | { 19 | client.WriteArray(kIndex1, kData1.c_str(), kData1.size()); 20 | client.WriteArray(kIndex2, kData2, sizeof(kData2)); 21 | } 22 | 23 | void CheckData(UntypedClient& client) 24 | { 25 | char result_s[20]; 26 | client.ReadArray(kIndex1, result_s, kData1.size()); 27 | assert( ! memcmp(result_s, kData1.c_str(), kData1.size()) ); 28 | 29 | unsigned char result_a[20]; 30 | client.ReadArray(kIndex2, result_a, sizeof(kData2)); 31 | assert( ! memcmp(result_a, kData2, sizeof(kData2) ) ); 32 | } 33 | 34 | int main() 35 | { 36 | UntypedClient client("array_test.log"); 37 | client.ClearCache(); 38 | 39 | cout << "Start test..." << endl; 40 | 41 | InitData(client); 42 | 43 | CheckData(client); 44 | } 45 | -------------------------------------------------------------------------------- /test/get_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "typed_client.h" 6 | 7 | using namespace std; 8 | using namespace zero_cache; 9 | 10 | static const size_t kIndex1 = 0; 11 | static const long kData1 = 1024; 12 | 13 | static const size_t kIndex2 = 1; 14 | static const double kData2 = 17.255; 15 | 16 | void InitData(TypedClient& client) 17 | { 18 | client.WriteLong(kIndex1, kData1); 19 | client.WriteDouble(kIndex2, kData2); 20 | } 21 | 22 | void CheckData(TypedClient& client) 23 | { 24 | long result_l = client.ReadLong(kIndex1); 25 | assert( result_l == kData1 ); 26 | 27 | double result_d = client.ReadDouble(kIndex2); 28 | assert( result_d == kData2 ); 29 | } 30 | 31 | int main() 32 | { 33 | TypedClient client("get_test.log"); 34 | client.ClearCache(); 35 | 36 | cout << "Start test..." << endl; 37 | 38 | InitData(client); 39 | 40 | CheckData(client); 41 | } 42 | -------------------------------------------------------------------------------- /test/stress_array_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "untyped_client.h" 8 | #include "thread.h" 9 | 10 | using namespace std; 11 | using namespace zero_cache; 12 | 13 | void* WriteReadLoop(void* args) 14 | { 15 | const char* log_file = static_cast(args); 16 | UntypedClient client(log_file); 17 | 18 | char* endptr; 19 | size_t index = strtoul(log_file, &endptr, 10); 20 | char result[10]; 21 | 22 | while (true) 23 | { 24 | client.WriteArray(index, log_file, strlen(log_file)); 25 | usleep(1000); 26 | 27 | client.ReadArray(index, result, strlen(log_file)); 28 | assert( ! memcmp(result, log_file, strlen(log_file)) ); 29 | usleep(1000); 30 | } 31 | } 32 | 33 | void StartWriteThread(const char* args) 34 | { 35 | CreateThread(WriteReadLoop, const_cast(args)); 36 | } 37 | 38 | void WaitInput() 39 | { 40 | char key; 41 | cin >> key; 42 | } 43 | 44 | int main() 45 | { 46 | UntypedClient client(""); 47 | client.ClearCache(); 48 | 49 | cout << "Start test..." << endl; 50 | 51 | StartWriteThread("1"); 52 | StartWriteThread("2"); 53 | StartWriteThread("3"); 54 | StartWriteThread("4"); 55 | StartWriteThread("5"); 56 | StartWriteThread("6"); 57 | StartWriteThread("7"); 58 | StartWriteThread("8"); 59 | StartWriteThread("9"); 60 | StartWriteThread("10"); 61 | StartWriteThread("11"); 62 | StartWriteThread("12"); 63 | StartWriteThread("13"); 64 | StartWriteThread("14"); 65 | StartWriteThread("15"); 66 | StartWriteThread("16"); 67 | 68 | WaitInput(); 69 | } 70 | -------------------------------------------------------------------------------- /test/stress_value_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "typed_client.h" 7 | #include "thread.h" 8 | 9 | using namespace std; 10 | using namespace zero_cache; 11 | 12 | void* WriteReadLoop(void* args) 13 | { 14 | const char* log_file = static_cast(args); 15 | TypedClient client(log_file); 16 | 17 | char* endptr; 18 | size_t index = strtoul(log_file, &endptr, 10); 19 | long data = index; 20 | long result; 21 | 22 | while (true) 23 | { 24 | client.WriteLong(index, data); 25 | usleep(1000); 26 | 27 | result = client.ReadLong(index); 28 | assert( result == data ); 29 | usleep(1000); 30 | } 31 | } 32 | 33 | void StartWriteThread(const char* args) 34 | { 35 | CreateThread(WriteReadLoop, const_cast(args)); 36 | } 37 | 38 | void WaitInput() 39 | { 40 | char key; 41 | cin >> key; 42 | } 43 | 44 | int main() 45 | { 46 | TypedClient client(""); 47 | client.ClearCache(); 48 | 49 | cout << "Start test..." << endl; 50 | 51 | StartWriteThread("1"); 52 | StartWriteThread("2"); 53 | StartWriteThread("3"); 54 | StartWriteThread("4"); 55 | StartWriteThread("5"); 56 | StartWriteThread("6"); 57 | StartWriteThread("7"); 58 | StartWriteThread("8"); 59 | StartWriteThread("9"); 60 | StartWriteThread("10"); 61 | StartWriteThread("11"); 62 | StartWriteThread("12"); 63 | StartWriteThread("13"); 64 | StartWriteThread("14"); 65 | StartWriteThread("15"); 66 | StartWriteThread("16"); 67 | 68 | WaitInput(); 69 | } 70 | --------------------------------------------------------------------------------